From 216c7af2283d3965fdd30c9aa5558898659891ff Mon Sep 17 00:00:00 2001 From: Tom Watkins Date: Tue, 11 Mar 2025 17:28:01 +0000 Subject: [PATCH 1/5] Add filters to controller + tests --- .../v1/person/AddressController.kt | 18 ++- .../services/GetAddressesForPersonService.kt | 6 +- .../person/sentences/AddressControllerTest.kt | 108 +++++++++--------- .../person/AddressIntegrationTest.kt | 22 +++- .../GetAddressesForPersonServiceTest.kt | 19 +-- 5 files changed, 106 insertions(+), 67 deletions(-) diff --git a/src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/controllers/v1/person/AddressController.kt b/src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/controllers/v1/person/AddressController.kt index 7f583b3b2..419a9bb18 100644 --- a/src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/controllers/v1/person/AddressController.kt +++ b/src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/controllers/v1/person/AddressController.kt @@ -6,16 +6,18 @@ import io.swagger.v3.oas.annotations.media.Content import io.swagger.v3.oas.annotations.media.Schema import io.swagger.v3.oas.annotations.responses.ApiResponse import io.swagger.v3.oas.annotations.tags.Tag +import jakarta.validation.ValidationException import org.springframework.beans.factory.annotation.Autowired import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.PathVariable +import org.springframework.web.bind.annotation.RequestAttribute import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RestController import uk.gov.justice.digital.hmpps.hmppsintegrationapi.exception.EntityNotFoundException -import uk.gov.justice.digital.hmpps.hmppsintegrationapi.extensions.decodeUrlCharacters import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.Address import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.DataResponse import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.UpstreamApiError +import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.roleconfig.ConsumerFilters import uk.gov.justice.digital.hmpps.hmppsintegrationapi.services.GetAddressesForPersonService import uk.gov.justice.digital.hmpps.hmppsintegrationapi.services.internal.AuditService @@ -26,26 +28,32 @@ class AddressController( @Autowired val auditService: AuditService, @Autowired val getAddressesForPersonService: GetAddressesForPersonService, ) { - @GetMapping("{encodedHmppsId}/addresses") + @GetMapping("{hmppsId}/addresses") @Operation( summary = "Returns addresses associated with a person, ordered by startDate.", responses = [ ApiResponse(responseCode = "200", useReturnTypeSchema = true, description = "Successfully found a person with the provided HMPPS ID."), + ApiResponse(responseCode = "400", content = [Content(schema = Schema(ref = "#/components/schemas/BadRequest"))]), ApiResponse(responseCode = "404", content = [Content(schema = Schema(ref = "#/components/schemas/PersonNotFound"))]), ApiResponse(responseCode = "500", content = [Content(schema = Schema(ref = "#/components/schemas/InternalServerError"))]), ], ) fun getPersonAddresses( - @Parameter(description = "A URL-encoded HMPPS identifier", example = "2008%2F0545166T") @PathVariable encodedHmppsId: String, + @Parameter(description = "The HMPPS ID of the person", example = "G2996UX") @PathVariable hmppsId: String, + @RequestAttribute filters: ConsumerFilters?, ): DataResponse> { - val hmppsId = encodedHmppsId.decodeUrlCharacters() - val response = getAddressesForPersonService.execute(hmppsId) + val response = getAddressesForPersonService.execute(hmppsId, filters) + + if (response.hasError(UpstreamApiError.Type.BAD_REQUEST)) { + throw ValidationException("Invalid id: $hmppsId") + } if (response.hasError(UpstreamApiError.Type.ENTITY_NOT_FOUND)) { throw EntityNotFoundException("Could not find person with id: $hmppsId") } auditService.createEvent("GET_PERSON_ADDRESS", mapOf("hmppsId" to hmppsId)) + return DataResponse(response.data) } } diff --git a/src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/services/GetAddressesForPersonService.kt b/src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/services/GetAddressesForPersonService.kt index e46c7696b..2dfc8fff5 100644 --- a/src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/services/GetAddressesForPersonService.kt +++ b/src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/services/GetAddressesForPersonService.kt @@ -7,6 +7,7 @@ import uk.gov.justice.digital.hmpps.hmppsintegrationapi.gateways.ProbationOffend import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.Address import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.Response import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.UpstreamApiError +import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.roleconfig.ConsumerFilters @Service class GetAddressesForPersonService( @@ -14,7 +15,10 @@ class GetAddressesForPersonService( @Autowired val getPersonService: GetPersonService, @Autowired val probationOffenderSearchGateway: ProbationOffenderSearchGateway, ) { - fun execute(hmppsId: String): Response> { + fun execute( + hmppsId: String, + filters: ConsumerFilters?, + ): Response> { val personResponse = getPersonService.execute(hmppsId = hmppsId) if (personResponse.errors.isNotEmpty()) { return Response(data = emptyList(), errors = personResponse.errors) diff --git a/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/controllers/v1/person/sentences/AddressControllerTest.kt b/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/controllers/v1/person/sentences/AddressControllerTest.kt index 6403861c7..85a0780c7 100644 --- a/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/controllers/v1/person/sentences/AddressControllerTest.kt +++ b/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/controllers/v1/person/sentences/AddressControllerTest.kt @@ -5,6 +5,7 @@ import io.kotest.matchers.shouldBe import org.mockito.Mockito import org.mockito.internal.verification.VerificationModeFactory import org.mockito.kotlin.doThrow +import org.mockito.kotlin.times import org.mockito.kotlin.verify import org.mockito.kotlin.whenever import org.springframework.beans.factory.annotation.Autowired @@ -22,8 +23,6 @@ import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.UpstreamApi import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.UpstreamApiError import uk.gov.justice.digital.hmpps.hmppsintegrationapi.services.GetAddressesForPersonService import uk.gov.justice.digital.hmpps.hmppsintegrationapi.services.internal.AuditService -import java.net.URLEncoder -import java.nio.charset.StandardCharsets @WebMvcTest(controllers = [AddressController::class]) @ActiveProfiles("test") @@ -33,76 +32,84 @@ internal class AddressControllerTest( @MockitoBean val auditService: AuditService, ) : DescribeSpec( { - val hmppsId = "2003/13116M" - val encodedHmppsId = URLEncoder.encode(hmppsId, StandardCharsets.UTF_8) - val basePath = "/v1/persons" + val hmppsId = "G2996UX" + val path = "/v1/persons/$hmppsId/addresses" + val filters = null val mockMvc = IntegrationAPIMockMvc(springMockMvc) - describe("GET $basePath/{encodedHmppsId}/addresses") { + describe("GET $path") { beforeTest { Mockito.reset(getAddressesForPersonService) Mockito.reset(auditService) - whenever(getAddressesForPersonService.execute(hmppsId)).thenReturn(Response(data = listOf(generateTestAddress()))) - } - - it("returns a 200 OK status code") { - val result = mockMvc.performAuthorised("$basePath/$encodedHmppsId/addresses") - - result.response.status.shouldBe(HttpStatus.OK.value()) - } - - it("gets the addresses for a person with the matching ID") { - mockMvc.performAuthorised("$basePath/$encodedHmppsId/addresses") - verify(getAddressesForPersonService, VerificationModeFactory.times(1)).execute(hmppsId) + whenever(getAddressesForPersonService.execute(hmppsId, null)).thenReturn(Response(data = listOf(generateTestAddress()))) } - it("returns the addresses for a person with the matching ID") { - val result = mockMvc.performAuthorised("$basePath/$encodedHmppsId/addresses") + it("returns a 200 OK status code with data") { + val result = mockMvc.performAuthorised(path) + result.response.status.shouldBe(HttpStatus.OK.value()) result.response.contentAsString.shouldBe( """ - { - "data": [ { - "country": "England", - "county": "Greater London", - "endDate": "2023-05-20", - "locality": "London Bridge", - "name": "The chocolate factory", - "noFixedAddress": false, - "number": "89", - "postcode": "SE1 1TZ", - "startDate": "2021-05-10", - "street": "Omeara", - "town": "London Town", - "types": [ - { - "code": "A99", - "description": "Chocolate Factory" - }, + "data": [ { - "code": "B99", - "description": "Glass Elevator" + "country": "England", + "county": "Greater London", + "endDate": "2023-05-20", + "locality": "London Bridge", + "name": "The chocolate factory", + "noFixedAddress": false, + "number": "89", + "postcode": "SE1 1TZ", + "startDate": "2021-05-10", + "street": "Omeara", + "town": "London Town", + "types": [ + { + "code": "A99", + "description": "Chocolate Factory" + }, + { + "code": "B99", + "description": "Glass Elevator" + } + ], + "notes": "some interesting note" } - ], - "notes": "some interesting note" + ] } - ] - } - """.removeWhitespaceAndNewlines(), + """.removeWhitespaceAndNewlines(), ) } it("logs audit") { - mockMvc.performAuthorised("$basePath/$encodedHmppsId/addresses") + mockMvc.performAuthorised(path) verify( auditService, VerificationModeFactory.times(1), ).createEvent("GET_PERSON_ADDRESS", mapOf("hmppsId" to hmppsId)) } + it("returns a 400 BAD REQUEST status code when bad request error is returned from address service") { + whenever(getAddressesForPersonService.execute(hmppsId, filters)).thenReturn( + Response( + data = emptyList(), + errors = + listOf( + UpstreamApiError( + causedBy = UpstreamApi.NOMIS, + type = UpstreamApiError.Type.BAD_REQUEST, + ), + ), + ), + ) + + val result = mockMvc.performAuthorised(path) + result.response.status.shouldBe(HttpStatus.BAD_REQUEST.value()) + } + it("returns a 404 NOT FOUND status code when entity not found error is returned from address service") { - whenever(getAddressesForPersonService.execute(hmppsId)).thenReturn( + whenever(getAddressesForPersonService.execute(hmppsId, filters)).thenReturn( Response( data = emptyList(), errors = @@ -115,17 +122,16 @@ internal class AddressControllerTest( ), ) - val result = mockMvc.performAuthorised("$basePath/$encodedHmppsId/addresses") - + val result = mockMvc.performAuthorised(path) result.response.status.shouldBe(HttpStatus.NOT_FOUND.value()) } it("returns a 500 INTERNAL SERVER ERROR status code when upstream api return expected error") { - whenever(getAddressesForPersonService.execute(hmppsId)).doThrow( + whenever(getAddressesForPersonService.execute(hmppsId, filters)).doThrow( WebClientResponseException(500, "MockError", null, null, null, null), ) - val result = mockMvc.performAuthorised("$basePath/$encodedHmppsId/addresses") + val result = mockMvc.performAuthorised(path) assert(result.response.status == 500) assert( result.response.contentAsString.equals( diff --git a/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/integration/person/AddressIntegrationTest.kt b/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/integration/person/AddressIntegrationTest.kt index 94c21ab49..8664c9756 100644 --- a/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/integration/person/AddressIntegrationTest.kt +++ b/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/integration/person/AddressIntegrationTest.kt @@ -6,10 +6,30 @@ import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status import uk.gov.justice.digital.hmpps.hmppsintegrationapi.integration.IntegrationTestBase class AddressIntegrationTest : IntegrationTestBase() { + val path = "$basePath/$nomsId/addresses" + @Test fun `returns addresses for a person`() { - callApi("$basePath/$pnc/addresses") + callApi(path) .andExpect(status().isOk) .andExpect(content().json(getExpectedResponse("person-addresses"))) } + + @Test + fun `sentences returns a 400 if the hmppsId is invalid`() { + callApi("$basePath/$invalidNomsId/addresses") + .andExpect(status().isBadRequest) + } + + @Test + fun `sentences returns a 404 for if consumer has empty list of prisons`() { + callApiWithCN(path, noPrisonsCn) + .andExpect(status().isNotFound) + } + + @Test + fun `sentences returns a 404 for prisoner in wrong prison`() { + callApiWithCN(path, limitedPrisonsCn) + .andExpect(status().isNotFound) + } } diff --git a/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/services/GetAddressesForPersonServiceTest.kt b/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/services/GetAddressesForPersonServiceTest.kt index 1e0a85ef3..c7e543061 100644 --- a/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/services/GetAddressesForPersonServiceTest.kt +++ b/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/services/GetAddressesForPersonServiceTest.kt @@ -31,6 +31,7 @@ internal class GetAddressesForPersonServiceTest( val hmppsId = "2003/13116M" val prisonerNumber = "A5553AA" val deliusCrn = "X777776" + val filters = null val person = Person(firstName = "Qui-gon", lastName = "Jin", identifiers = Identifiers(nomisNumber = prisonerNumber, deliusCrn = deliusCrn)) @@ -91,7 +92,7 @@ internal class GetAddressesForPersonServiceTest( errors = errors, ), ) - val result = getAddressesForPersonService.execute(hmppsId) + val result = getAddressesForPersonService.execute(hmppsId, filters) result.errors.shouldBe(errors) } @@ -100,7 +101,7 @@ internal class GetAddressesForPersonServiceTest( whenever(probationOffenderSearchGateway.getAddressesForPerson(hmppsId)).thenReturn(Response(data = listOf(deliusAddress))) whenever(nomisGateway.getAddressesForPerson(prisonerNumber)).thenReturn(Response(data = listOf(nomisAddress))) - val result = getAddressesForPersonService.execute(hmppsId) + val result = getAddressesForPersonService.execute(hmppsId, filters) result.errors.shouldBeEmpty() result.data.shouldBe(listOf(nomisAddress, deliusAddress)) } @@ -121,7 +122,7 @@ internal class GetAddressesForPersonServiceTest( ), ) - val result = getAddressesForPersonService.execute(hmppsId) + val result = getAddressesForPersonService.execute(hmppsId, filters) result.errors.shouldBeEmpty() result.data.shouldBe(listOf(deliusAddress)) } @@ -142,7 +143,7 @@ internal class GetAddressesForPersonServiceTest( ) whenever(nomisGateway.getAddressesForPerson(prisonerNumber)).thenReturn(Response(data = listOf(nomisAddress))) - val result = getAddressesForPersonService.execute(hmppsId) + val result = getAddressesForPersonService.execute(hmppsId, filters) result.errors.shouldBeEmpty() result.data.shouldBe(listOf(nomisAddress)) } @@ -163,7 +164,7 @@ internal class GetAddressesForPersonServiceTest( ), ) - val result = getAddressesForPersonService.execute(hmppsId) + val result = getAddressesForPersonService.execute(hmppsId, filters) result.errors.shouldBe(listOf(UpstreamApiError(type = UpstreamApiError.Type.INTERNAL_SERVER_ERROR, causedBy = UpstreamApi.NOMIS))) } @@ -194,7 +195,7 @@ internal class GetAddressesForPersonServiceTest( ), ) - val result = getAddressesForPersonService.execute(hmppsId) + val result = getAddressesForPersonService.execute(hmppsId, filters) result.errors.shouldBe(listOf(UpstreamApiError(type = UpstreamApiError.Type.INTERNAL_SERVER_ERROR, causedBy = UpstreamApi.NOMIS))) } @@ -213,7 +214,7 @@ internal class GetAddressesForPersonServiceTest( ), ) - val result = getAddressesForPersonService.execute(hmppsId) + val result = getAddressesForPersonService.execute(hmppsId, filters) result.errors.shouldBe(listOf(UpstreamApiError(type = UpstreamApiError.Type.INTERNAL_SERVER_ERROR, causedBy = UpstreamApi.PROBATION_OFFENDER_SEARCH))) } @@ -221,7 +222,7 @@ internal class GetAddressesForPersonServiceTest( whenever(personService.execute(hmppsId = hmppsId)).thenReturn(Response(personNoNomis)) whenever(probationOffenderSearchGateway.getAddressesForPerson(hmppsId)).thenReturn(Response(listOf(deliusAddress))) - val result = getAddressesForPersonService.execute(hmppsId) + val result = getAddressesForPersonService.execute(hmppsId, filters) result.errors.shouldBeEmpty() result.data.shouldBe(listOf(deliusAddress)) } @@ -241,7 +242,7 @@ internal class GetAddressesForPersonServiceTest( ), ) - val result = getAddressesForPersonService.execute(hmppsId) + val result = getAddressesForPersonService.execute(hmppsId, filters) result.errors.shouldBe(listOf(UpstreamApiError(type = UpstreamApiError.Type.INTERNAL_SERVER_ERROR, causedBy = UpstreamApi.PROBATION_OFFENDER_SEARCH))) } }, From 9a809db21bd3d71102a7b433de8b948cabcd2391 Mon Sep 17 00:00:00 2001 From: Tom Watkins Date: Tue, 11 Mar 2025 17:41:36 +0000 Subject: [PATCH 2/5] Service changes + tests --- .../services/GetAddressesForPersonService.kt | 7 +-- .../GetAddressesForPersonServiceTest.kt | 43 ++++++++----------- 2 files changed, 20 insertions(+), 30 deletions(-) diff --git a/src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/services/GetAddressesForPersonService.kt b/src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/services/GetAddressesForPersonService.kt index 2dfc8fff5..b957a495e 100644 --- a/src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/services/GetAddressesForPersonService.kt +++ b/src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/services/GetAddressesForPersonService.kt @@ -19,7 +19,7 @@ class GetAddressesForPersonService( hmppsId: String, filters: ConsumerFilters?, ): Response> { - val personResponse = getPersonService.execute(hmppsId = hmppsId) + val personResponse = getPersonService.getNomisNumberWithPrisonFilter(hmppsId = hmppsId, filters) if (personResponse.errors.isNotEmpty()) { return Response(data = emptyList(), errors = personResponse.errors) } @@ -29,10 +29,7 @@ class GetAddressesForPersonService( return Response(data = emptyList(), errors = addressesFromDelius.errors) } - val nomisNumber = personResponse.data?.identifiers?.nomisNumber - if (nomisNumber == null) { - return addressesFromDelius - } + val nomisNumber = personResponse.data?.nomisNumber ?: return addressesFromDelius val addressesFromNomis = nomisGateway.getAddressesForPerson(id = nomisNumber) if (hasErrorOtherThanEntityNotFound(addressesFromNomis)) { diff --git a/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/services/GetAddressesForPersonServiceTest.kt b/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/services/GetAddressesForPersonServiceTest.kt index c7e543061..49ee0fc21 100644 --- a/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/services/GetAddressesForPersonServiceTest.kt +++ b/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/services/GetAddressesForPersonServiceTest.kt @@ -11,8 +11,7 @@ import org.springframework.test.context.bean.override.mockito.MockitoBean import uk.gov.justice.digital.hmpps.hmppsintegrationapi.gateways.NomisGateway import uk.gov.justice.digital.hmpps.hmppsintegrationapi.gateways.ProbationOffenderSearchGateway import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.Address -import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.Identifiers -import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.Person +import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.NomisNumber import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.Response import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.UpstreamApi import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.UpstreamApiError @@ -28,17 +27,10 @@ internal class GetAddressesForPersonServiceTest( private val getAddressesForPersonService: GetAddressesForPersonService, ) : DescribeSpec( { - val hmppsId = "2003/13116M" - val prisonerNumber = "A5553AA" - val deliusCrn = "X777776" + val hmppsId = "A5553AA" + val nomisNumber = "A5553AA" val filters = null - val person = - Person(firstName = "Qui-gon", lastName = "Jin", identifiers = Identifiers(nomisNumber = prisonerNumber, deliusCrn = deliusCrn)) - - val personNoNomis = - Person(firstName = "Qui-gon", lastName = "Jin", identifiers = Identifiers(deliusCrn = deliusCrn)) - val deliusAddress = Address( country = "UK", @@ -86,20 +78,21 @@ internal class GetAddressesForPersonServiceTest( description = "Mock error from person service", ), ) - whenever(personService.execute(hmppsId)).thenReturn( + whenever(personService.getNomisNumberWithPrisonFilter(hmppsId, filters)).thenReturn( Response( data = null, errors = errors, ), ) + val result = getAddressesForPersonService.execute(hmppsId, filters) result.errors.shouldBe(errors) } it("Nomis number, Delius success, Nomis success → Merge responses ") { - whenever(personService.execute(hmppsId = hmppsId)).thenReturn(Response(person)) + whenever(personService.getNomisNumberWithPrisonFilter(hmppsId, filters)).thenReturn(Response(NomisNumber(nomisNumber))) whenever(probationOffenderSearchGateway.getAddressesForPerson(hmppsId)).thenReturn(Response(data = listOf(deliusAddress))) - whenever(nomisGateway.getAddressesForPerson(prisonerNumber)).thenReturn(Response(data = listOf(nomisAddress))) + whenever(nomisGateway.getAddressesForPerson(nomisNumber)).thenReturn(Response(data = listOf(nomisAddress))) val result = getAddressesForPersonService.execute(hmppsId, filters) result.errors.shouldBeEmpty() @@ -107,9 +100,9 @@ internal class GetAddressesForPersonServiceTest( } it("Nomis number, Delius success, Nomis 404 → Ideally return just Delius response") { - whenever(personService.execute(hmppsId = hmppsId)).thenReturn(Response(person)) + whenever(personService.getNomisNumberWithPrisonFilter(hmppsId, filters)).thenReturn(Response(NomisNumber(nomisNumber))) whenever(probationOffenderSearchGateway.getAddressesForPerson(hmppsId)).thenReturn(Response(data = listOf(deliusAddress))) - whenever(nomisGateway.getAddressesForPerson(prisonerNumber)).thenReturn( + whenever(nomisGateway.getAddressesForPerson(nomisNumber)).thenReturn( Response( data = emptyList(), errors = @@ -128,7 +121,7 @@ internal class GetAddressesForPersonServiceTest( } it("Nomis number, Delius 404, nomis success → Return just NOMIS") { - whenever(personService.execute(hmppsId = hmppsId)).thenReturn(Response(person)) + whenever(personService.getNomisNumberWithPrisonFilter(hmppsId, filters)).thenReturn(Response(NomisNumber(nomisNumber))) whenever(probationOffenderSearchGateway.getAddressesForPerson(hmppsId)).thenReturn( Response( data = emptyList(), @@ -141,7 +134,7 @@ internal class GetAddressesForPersonServiceTest( ), ), ) - whenever(nomisGateway.getAddressesForPerson(prisonerNumber)).thenReturn(Response(data = listOf(nomisAddress))) + whenever(nomisGateway.getAddressesForPerson(nomisNumber)).thenReturn(Response(data = listOf(nomisAddress))) val result = getAddressesForPersonService.execute(hmppsId, filters) result.errors.shouldBeEmpty() @@ -149,9 +142,9 @@ internal class GetAddressesForPersonServiceTest( } it("Nomis number, Delius success, nomis non-404 error → Return NOMIS error") { - whenever(personService.execute(hmppsId = hmppsId)).thenReturn(Response(person)) + whenever(personService.getNomisNumberWithPrisonFilter(hmppsId, filters)).thenReturn(Response(NomisNumber(nomisNumber))) whenever(probationOffenderSearchGateway.getAddressesForPerson(hmppsId)).thenReturn(Response(listOf(deliusAddress))) - whenever(nomisGateway.getAddressesForPerson(prisonerNumber)).thenReturn( + whenever(nomisGateway.getAddressesForPerson(nomisNumber)).thenReturn( Response( data = emptyList(), errors = @@ -169,7 +162,7 @@ internal class GetAddressesForPersonServiceTest( } it("Nomis number, Delius 404, nomis any error (incl. 404) → Return just NOMIS") { - whenever(personService.execute(hmppsId = hmppsId)).thenReturn(Response(person)) + whenever(personService.getNomisNumberWithPrisonFilter(hmppsId, filters)).thenReturn(Response(NomisNumber(nomisNumber))) whenever(probationOffenderSearchGateway.getAddressesForPerson(hmppsId)).thenReturn( Response( data = emptyList(), @@ -182,7 +175,7 @@ internal class GetAddressesForPersonServiceTest( ), ), ) - whenever(nomisGateway.getAddressesForPerson(prisonerNumber)).thenReturn( + whenever(nomisGateway.getAddressesForPerson(nomisNumber)).thenReturn( Response( data = emptyList(), errors = @@ -200,7 +193,7 @@ internal class GetAddressesForPersonServiceTest( } it("Nomis number, Delius non-404 error → Return Delius response") { - whenever(personService.execute(hmppsId = hmppsId)).thenReturn(Response(person)) + whenever(personService.getNomisNumberWithPrisonFilter(hmppsId, filters)).thenReturn(Response(NomisNumber(nomisNumber))) whenever(probationOffenderSearchGateway.getAddressesForPerson(hmppsId)).thenReturn( Response( data = emptyList(), @@ -219,7 +212,7 @@ internal class GetAddressesForPersonServiceTest( } it("No nomis number, delius success → return Delius") { - whenever(personService.execute(hmppsId = hmppsId)).thenReturn(Response(personNoNomis)) + whenever(personService.getNomisNumberWithPrisonFilter(hmppsId, filters)).thenReturn(Response(NomisNumber(null))) whenever(probationOffenderSearchGateway.getAddressesForPerson(hmppsId)).thenReturn(Response(listOf(deliusAddress))) val result = getAddressesForPersonService.execute(hmppsId, filters) @@ -228,7 +221,7 @@ internal class GetAddressesForPersonServiceTest( } it("No nomis number, delius any error → return Delius") { - whenever(personService.execute(hmppsId = hmppsId)).thenReturn(Response(personNoNomis)) + whenever(personService.getNomisNumberWithPrisonFilter(hmppsId, filters)).thenReturn(Response(NomisNumber(null))) whenever(probationOffenderSearchGateway.getAddressesForPerson(hmppsId)).thenReturn( Response( data = emptyList(), From d42ab5ef5473f24e4ecacfe28c0078b52b347e6a Mon Sep 17 00:00:00 2001 From: Tom Watkins Date: Tue, 11 Mar 2025 17:45:59 +0000 Subject: [PATCH 3/5] Added endpoint to private-prison role --- src/main/resources/globals.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/globals.yml b/src/main/resources/globals.yml index 388e369e6..b0867f9a9 100644 --- a/src/main/resources/globals.yml +++ b/src/main/resources/globals.yml @@ -6,6 +6,7 @@ globals: - "/v1/hmpps/id/nomis-number/by-hmpps-id/[^/]*$" - "/v1/persons" - "/v1/persons/[^/]*$" + - "/v1/persons/.*/addresses" - "/v1/persons/.*/contacts[^/]*$" - "/v1/persons/.*/iep-level" - "/v1/persons/.*/visitor/.*/restrictions" From 4c6846ef98d892a1f61ff4b3896328fcf1919609 Mon Sep 17 00:00:00 2001 From: Tom Watkins Date: Tue, 11 Mar 2025 17:48:48 +0000 Subject: [PATCH 4/5] Corrected test names --- .../integration/person/AddressIntegrationTest.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/integration/person/AddressIntegrationTest.kt b/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/integration/person/AddressIntegrationTest.kt index 8664c9756..a60666572 100644 --- a/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/integration/person/AddressIntegrationTest.kt +++ b/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/integration/person/AddressIntegrationTest.kt @@ -16,19 +16,19 @@ class AddressIntegrationTest : IntegrationTestBase() { } @Test - fun `sentences returns a 400 if the hmppsId is invalid`() { + fun `returns a 400 if the hmppsId is invalid`() { callApi("$basePath/$invalidNomsId/addresses") .andExpect(status().isBadRequest) } @Test - fun `sentences returns a 404 for if consumer has empty list of prisons`() { + fun `returns a 404 for if consumer has empty list of prisons`() { callApiWithCN(path, noPrisonsCn) .andExpect(status().isNotFound) } @Test - fun `sentences returns a 404 for prisoner in wrong prison`() { + fun `returns a 404 for prisoner in wrong prison`() { callApiWithCN(path, limitedPrisonsCn) .andExpect(status().isNotFound) } From 63867d3385676b44f38d85a00ef1ce8bbbc2fb12 Mon Sep 17 00:00:00 2001 From: Tom Watkins Date: Wed, 12 Mar 2025 09:41:03 +0000 Subject: [PATCH 5/5] Add filter description --- .../controllers/v1/person/AddressController.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/controllers/v1/person/AddressController.kt b/src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/controllers/v1/person/AddressController.kt index 419a9bb18..b28817cb4 100644 --- a/src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/controllers/v1/person/AddressController.kt +++ b/src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/controllers/v1/person/AddressController.kt @@ -31,6 +31,7 @@ class AddressController( @GetMapping("{hmppsId}/addresses") @Operation( summary = "Returns addresses associated with a person, ordered by startDate.", + description = "Applicable filters:
  • prisons
", responses = [ ApiResponse(responseCode = "200", useReturnTypeSchema = true, description = "Successfully found a person with the provided HMPPS ID."), ApiResponse(responseCode = "400", content = [Content(schema = Schema(ref = "#/components/schemas/BadRequest"))]),