diff --git a/openapi.yml b/openapi.yml index fa9e54441..a3f886535 100644 --- a/openapi.yml +++ b/openapi.yml @@ -412,6 +412,48 @@ paths: PersonNotFoundError: $ref: "#/components/examples/PersonNotFoundError" + /v1/persons/{hmppsId}/risks/mappadetail: + get: + tags: + - persons + summary: Returns the mappa detail related to a person. + parameters: + - $ref: "#/components/parameters/HmppsId" + responses: + "200": + description: Successfully found mappa detail for a person with the provided HMPPS ID. + content: + application/json: + schema: + type: object + properties: + data: + type: object + properties: + level: + type: string + levelDescription: + type: string + category: + type: string + categoryDescription: + type: string + startDate: + type: string + reviewDate: + type: string + notes: + type: string + "404": + description: Failed to find risk-related mappa detail a person with the provided HMPPS ID. + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + examples: + PersonNotFoundError: + $ref: "#/components/examples/PersonNotFoundError" + /v1/persons/{hmppsId}/needs: get: tags: diff --git a/src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/controllers/v1/person/MappaDetailController.kt b/src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/controllers/v1/person/MappaDetailController.kt new file mode 100644 index 000000000..e5f186e08 --- /dev/null +++ b/src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/controllers/v1/person/MappaDetailController.kt @@ -0,0 +1,36 @@ +package uk.gov.justice.digital.hmpps.hmppsintegrationapi.controllers.v1.person + +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.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.MappaDetail +import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.UpstreamApiError +import uk.gov.justice.digital.hmpps.hmppsintegrationapi.services.GetMappaDetailForPersonService +import uk.gov.justice.digital.hmpps.hmppsintegrationapi.services.internal.AuditService + +@RestController +@RequestMapping("/v1/persons") +class MappaDetailController( + @Autowired val getMappaDetailForPersonService: GetMappaDetailForPersonService, + @Autowired val auditService: AuditService, +) { + + @GetMapping("{encodedHmppsId}/risks/mappadetail") + fun getMappaDetail( + @PathVariable encodedHmppsId: String, + + ): Map { + val hmppsId = encodedHmppsId.decodeUrlCharacters() + val response = getMappaDetailForPersonService.execute(hmppsId) + + if (response.hasError(UpstreamApiError.Type.ENTITY_NOT_FOUND)) { + throw EntityNotFoundException("Could not find person with id: $hmppsId") + } + auditService.createEvent("GET_MAPPA_DETAIL", "Mappa detail for person with hmpps id: $hmppsId has been retrieved") + return mapOf("data" to response.data) + } +} diff --git a/src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/gateways/NDeliusGateway.kt b/src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/gateways/NDeliusGateway.kt index 166f8039c..c179818f1 100644 --- a/src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/gateways/NDeliusGateway.kt +++ b/src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/gateways/NDeliusGateway.kt @@ -6,6 +6,7 @@ import org.springframework.http.HttpMethod import org.springframework.stereotype.Component import uk.gov.justice.digital.hmpps.hmppsintegrationapi.extensions.WebClientWrapper import uk.gov.justice.digital.hmpps.hmppsintegrationapi.extensions.WebClientWrapper.WebClientWrapperResponse +import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.MappaDetail import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.Offence import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.Response import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.Sentence @@ -63,6 +64,28 @@ class NDeliusGateway(@Value("\${services.ndelius.base-url}") baseUrl: String) { } } + fun getMappaDetailForPerson(id: String): Response { + val result = webClient.request( + HttpMethod.GET, + "/case/$id/supervisions", + authenticationHeader(), + UpstreamApi.NDELIUS, + ) + + return when (result) { + is WebClientWrapperResponse.Success -> { + Response(data = result.data.mappaDetail?.toMappaDetail()) + } + + is WebClientWrapperResponse.Error -> { + Response( + data = null, + errors = result.errors, + ) + } + } + } + private fun authenticationHeader(): Map { val token = hmppsAuthGateway.getClientToken("nDelius") diff --git a/src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/models/hmpps/MappaDetail.kt b/src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/models/hmpps/MappaDetail.kt new file mode 100644 index 000000000..a3cdf7183 --- /dev/null +++ b/src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/models/hmpps/MappaDetail.kt @@ -0,0 +1,11 @@ +package uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps + +data class MappaDetail( + val level: Int? = null, + val levelDescription: String? = null, + val category: Int? = null, + val categoryDescription: String? = null, + val startDate: String? = null, + val reviewDate: String? = null, + val notes: String? = null, +) diff --git a/src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/models/ndelius/NDeliusMappaDetail.kt b/src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/models/ndelius/NDeliusMappaDetail.kt new file mode 100644 index 000000000..a1ebaa335 --- /dev/null +++ b/src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/models/ndelius/NDeliusMappaDetail.kt @@ -0,0 +1,25 @@ +package uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.ndelius + +import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.MappaDetail + +data class NDeliusMappaDetail( + val level: Int? = null, + val levelDescription: String? = null, + val category: Int? = null, + val categoryDescription: String? = null, + val startDate: String? = null, + val reviewDate: String? = null, + val notes: String? = null, +) { + fun toMappaDetail(): MappaDetail = ( + MappaDetail( + level = this.level, + levelDescription = this.levelDescription, + category = this.category, + categoryDescription = this.categoryDescription, + startDate = this.startDate, + reviewDate = this.reviewDate, + notes = this.notes, + ) + ) +} diff --git a/src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/models/ndelius/NDeliusSupervisions.kt b/src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/models/ndelius/NDeliusSupervisions.kt index df0ca19b8..f49f1efdb 100644 --- a/src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/models/ndelius/NDeliusSupervisions.kt +++ b/src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/models/ndelius/NDeliusSupervisions.kt @@ -1,5 +1,6 @@ package uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.ndelius data class NDeliusSupervisions( + val mappaDetail: NDeliusMappaDetail ? = null, val supervisions: List, ) diff --git a/src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/services/GetMappaDetailForPersonService.kt b/src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/services/GetMappaDetailForPersonService.kt new file mode 100644 index 000000000..e3539d056 --- /dev/null +++ b/src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/services/GetMappaDetailForPersonService.kt @@ -0,0 +1,29 @@ +package uk.gov.justice.digital.hmpps.hmppsintegrationapi.services + +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.stereotype.Service +import uk.gov.justice.digital.hmpps.hmppsintegrationapi.gateways.NDeliusGateway +import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.MappaDetail +import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.Response + +@Service +class GetMappaDetailForPersonService( + @Autowired val getPersonService: GetPersonService, + @Autowired val nDeliusGateway: NDeliusGateway, +) { + fun execute(hmppsId: String): Response { + val personResponse = getPersonService.execute(hmppsId = hmppsId) + + val deliusCrn = personResponse.data?.identifiers?.deliusCrn + var nDeliusMappaDetailResponse: Response = Response(data = MappaDetail()) + + if (deliusCrn != null) { + nDeliusMappaDetailResponse = nDeliusGateway.getMappaDetailForPerson(id = deliusCrn) + } + + return Response( + data = nDeliusMappaDetailResponse.data, + errors = nDeliusMappaDetailResponse.errors, + ) + } +} diff --git a/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/controllers/v1/person/MappaDetailControllerTest.kt b/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/controllers/v1/person/MappaDetailControllerTest.kt new file mode 100644 index 000000000..309ac19be --- /dev/null +++ b/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/controllers/v1/person/MappaDetailControllerTest.kt @@ -0,0 +1,114 @@ +package uk.gov.justice.digital.hmpps.hmppsintegrationapi.controllers.v1.person + +import io.kotest.core.spec.style.DescribeSpec +import io.kotest.matchers.shouldBe +import io.kotest.matchers.string.shouldContain +import org.mockito.Mockito +import org.mockito.internal.verification.VerificationModeFactory +import org.mockito.kotlin.verify +import org.mockito.kotlin.whenever +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest +import org.springframework.boot.test.mock.mockito.MockBean +import org.springframework.http.HttpStatus +import org.springframework.test.context.ActiveProfiles +import org.springframework.test.web.servlet.MockMvc +import uk.gov.justice.digital.hmpps.hmppsintegrationapi.extensions.removeWhitespaceAndNewlines +import uk.gov.justice.digital.hmpps.hmppsintegrationapi.helpers.IntegrationAPIMockMvc +import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.MappaDetail +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 +import uk.gov.justice.digital.hmpps.hmppsintegrationapi.services.GetMappaDetailForPersonService +import uk.gov.justice.digital.hmpps.hmppsintegrationapi.services.internal.AuditService +import java.net.URLEncoder +import java.nio.charset.StandardCharsets + +@WebMvcTest(controllers = [MappaDetailController::class]) +@ActiveProfiles("test") +internal class MappaDetailControllerTest( + @Autowired var springMockMvc: MockMvc, + @MockBean val getMappaDetailForPersonService: GetMappaDetailForPersonService, + @MockBean val auditService: AuditService, +) : DescribeSpec( + { + val hmppsId = "9999/11111A" + val encodedHmppsId = URLEncoder.encode(hmppsId, StandardCharsets.UTF_8) + val path = "/v1/persons/$encodedHmppsId/risks/mappadetail" + val mockMvc = IntegrationAPIMockMvc(springMockMvc) + + describe("GET $path") { + beforeTest { + Mockito.reset(getMappaDetailForPersonService) + whenever(getMappaDetailForPersonService.execute(hmppsId)).thenReturn( + Response( + MappaDetail( + level = 2, + levelDescription = "A high level of risk", + category = 3, + categoryDescription = "Behaviour", + startDate = "2024-03-08", + reviewDate = "2024-10-08", + notes = "Review in a week", + ), + ), + ) + + Mockito.reset(auditService) + } + + it("returns a 200 OK status code") { + val result = mockMvc.performAuthorised(path) + + result.response.status.shouldBe(HttpStatus.OK.value()) + } + + it("gets the mappa detail for a person with the matching ID") { + mockMvc.performAuthorised(path) + verify(getMappaDetailForPersonService, VerificationModeFactory.times(1)).execute(hmppsId) + } + + it("logs audit") { + mockMvc.performAuthorised(path) + + verify(auditService, VerificationModeFactory.times(1)).createEvent("GET_MAPPA_DETAIL", "Mappa detail for person with hmpps id: $hmppsId has been retrieved") + } + + it("returns the risk categories for a person with the matching ID") { + val result = mockMvc.performAuthorised(path) + + result.response.contentAsString.shouldContain( + """ + "data": { + "level": 2, + "levelDescription": "A high level of risk", + "category": 3, + "categoryDescription": "Behaviour", + "startDate": "2024-03-08", + "reviewDate": "2024-10-08", + "notes": "Review in a week" + } + """.removeWhitespaceAndNewlines(), + ) + } + + it("returns a 404 NOT FOUND status code when person isn't found in the upstream API") { + whenever(getMappaDetailForPersonService.execute(hmppsId)).thenReturn( + Response( + data = MappaDetail(), + errors = listOf( + UpstreamApiError( + causedBy = UpstreamApi.PROBATION_OFFENDER_SEARCH, + type = UpstreamApiError.Type.ENTITY_NOT_FOUND, + ), + ), + ), + ) + + val result = mockMvc.performAuthorised(path) + + result.response.status.shouldBe(HttpStatus.NOT_FOUND.value()) + } + } + }, +) diff --git a/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/gateways/ndelius/GetMappaDetailForPersonTest.kt b/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/gateways/ndelius/GetMappaDetailForPersonTest.kt new file mode 100644 index 000000000..e77e031bb --- /dev/null +++ b/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/gateways/ndelius/GetMappaDetailForPersonTest.kt @@ -0,0 +1,101 @@ +package uk.gov.justice.digital.hmpps.hmppsintegrationapi.gateways.ndelius + +import io.kotest.core.spec.style.DescribeSpec +import io.kotest.matchers.collections.shouldHaveSize +import io.kotest.matchers.shouldBe +import org.mockito.Mockito +import org.mockito.internal.verification.VerificationModeFactory +import org.mockito.kotlin.verify +import org.mockito.kotlin.whenever +import org.springframework.boot.test.context.ConfigDataApplicationContextInitializer +import org.springframework.boot.test.mock.mockito.MockBean +import org.springframework.http.HttpStatus +import org.springframework.test.context.ActiveProfiles +import org.springframework.test.context.ContextConfiguration +import uk.gov.justice.digital.hmpps.hmppsintegrationapi.gateways.HmppsAuthGateway +import uk.gov.justice.digital.hmpps.hmppsintegrationapi.gateways.NDeliusGateway +import uk.gov.justice.digital.hmpps.hmppsintegrationapi.mockservers.HmppsAuthMockServer +import uk.gov.justice.digital.hmpps.hmppsintegrationapi.mockservers.NDeliusApiMockServer +import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.MappaDetail +import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.UpstreamApi +import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.UpstreamApiError +import java.io.File + +@ActiveProfiles("test") +@ContextConfiguration( + initializers = [ConfigDataApplicationContextInitializer::class], + classes = [NDeliusGateway::class], +) +class GetMappaDetailForPersonTest( + @MockBean val hmppsAuthGateway: HmppsAuthGateway, + val nDeliusGateway: NDeliusGateway, +) : + DescribeSpec( + { + val nDeliusApiMockServer = NDeliusApiMockServer() + val deliusCrn = "X777776" + + beforeEach { + nDeliusApiMockServer.start() + nDeliusApiMockServer.stubGetSupervisionsForPerson( + deliusCrn, + File("src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/gateways/ndelius/fixtures/GetSupervisionsResponse.json").readText(), + ) + + Mockito.reset(hmppsAuthGateway) + whenever(hmppsAuthGateway.getClientToken("nDelius")).thenReturn(HmppsAuthMockServer.TOKEN) + } + + afterTest { + nDeliusApiMockServer.stop() + } + + it("authenticates using HMPPS Auth with credentials") { + nDeliusGateway.getMappaDetailForPerson(deliusCrn) + + verify(hmppsAuthGateway, VerificationModeFactory.times(1)).getClientToken("nDelius") + } + + it("returns Mappa detail for the matching CRN") { + val response = nDeliusGateway.getMappaDetailForPerson(deliusCrn) + + response.data.shouldBe( + MappaDetail( + level = 1, + levelDescription = "string", + category = 1, + categoryDescription = "string", + startDate = "string", + reviewDate = "string", + notes = "string", + ), + ) + } + + it("returns an empty list if no mappa detail is found") { + nDeliusApiMockServer.stubGetSupervisionsForPerson( + deliusCrn, + """ + { + "mappaDetail": {}, + "supervisions": [] + } + """, + ) + + val response = nDeliusGateway.getMappaDetailForPerson(deliusCrn) + + response.data.shouldBe(MappaDetail()) + } + + it("returns an error when 404 Not Found is returned because no person is found") { + nDeliusApiMockServer.stubGetSupervisionsForPerson(deliusCrn, "", HttpStatus.NOT_FOUND) + + val response = nDeliusGateway.getMappaDetailForPerson(deliusCrn) + + response.errors.shouldHaveSize(1) + response.errors.first().causedBy.shouldBe(UpstreamApi.NDELIUS) + response.errors.first().type.shouldBe(UpstreamApiError.Type.ENTITY_NOT_FOUND) + } + }, + ) diff --git a/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/gateways/ndelius/GetOffencesForPersonTest.kt b/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/gateways/ndelius/GetOffencesForPersonTest.kt index 41e6278a4..cbcacc5f1 100644 --- a/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/gateways/ndelius/GetOffencesForPersonTest.kt +++ b/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/gateways/ndelius/GetOffencesForPersonTest.kt @@ -131,7 +131,9 @@ class GetOffencesForPersonTest( nDeliusApiMockServer.stubGetSupervisionsForPerson( deliusCrn, """ - { "supervisions": [] } + { + "mappaDetail": null, + "supervisions": [] } """, ) diff --git a/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/gateways/ndelius/GetSentencesForPersonTest.kt b/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/gateways/ndelius/GetSentencesForPersonTest.kt index 15e97727a..a08f90888 100644 --- a/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/gateways/ndelius/GetSentencesForPersonTest.kt +++ b/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/gateways/ndelius/GetSentencesForPersonTest.kt @@ -99,7 +99,9 @@ class GetSentencesForPersonTest( nDeliusApiMockServer.stubGetSupervisionsForPerson( deliusCrn, """ - { "supervisions": [] } + { + "mappaDetail": {}, + "supervisions": [] } """, ) diff --git a/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/gateways/ndelius/fixtures/GetSupervisionsResponse.json b/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/gateways/ndelius/fixtures/GetSupervisionsResponse.json index 27670afd5..121848853 100644 --- a/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/gateways/ndelius/fixtures/GetSupervisionsResponse.json +++ b/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/gateways/ndelius/fixtures/GetSupervisionsResponse.json @@ -1,4 +1,13 @@ { + "mappaDetail": { + "level": 1, + "levelDescription": "string", + "category": 1, + "categoryDescription": "string", + "startDate": "string", + "reviewDate": "string", + "notes": "string" + }, "supervisions": [ { "number": 1, diff --git a/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/models/ndelius/SupervisionsTest.kt b/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/models/ndelius/SupervisionsTest.kt index b48214ece..e04f1dbcb 100644 --- a/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/models/ndelius/SupervisionsTest.kt +++ b/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/models/ndelius/SupervisionsTest.kt @@ -16,6 +16,7 @@ class SupervisionsTest : DescribeSpec( describe("When there are additional offences") { it("maps one-to-one attributes to integration API attributes") { val supervisions = NDeliusSupervisions( + mappaDetail = NDeliusMappaDetail(), supervisions = listOf( NDeliusSupervision( custodial = true, @@ -73,6 +74,7 @@ class SupervisionsTest : DescribeSpec( } it("does not local date parse additional offence date if no date is provided") { val supervisions = NDeliusSupervisions( + mappaDetail = NDeliusMappaDetail(), supervisions = listOf( NDeliusSupervision( custodial = true, @@ -109,6 +111,7 @@ class SupervisionsTest : DescribeSpec( it("does local date parse additional offence date if a date is provided") { val supervisions = NDeliusSupervisions( + mappaDetail = NDeliusMappaDetail(), supervisions = listOf( NDeliusSupervision( custodial = true, @@ -147,6 +150,7 @@ class SupervisionsTest : DescribeSpec( describe("When there are no additional offences") { it("maps one-to-one attributes to integration API attributes") { val supervisions = NDeliusSupervisions( + mappaDetail = NDeliusMappaDetail(), supervisions = listOf( NDeliusSupervision( custodial = true, @@ -191,6 +195,7 @@ class SupervisionsTest : DescribeSpec( describe("#toSentence") { it("maps one-to-one attributes to integration API sentence attributes") { val supervisions = NDeliusSupervisions( + mappaDetail = NDeliusMappaDetail(), listOf( NDeliusSupervision( active = true, @@ -248,6 +253,7 @@ class SupervisionsTest : DescribeSpec( it("can be constructed with NULL values") { val supervisions = NDeliusSupervisions( + mappaDetail = NDeliusMappaDetail(), listOf( NDeliusSupervision(custodial = true), ), diff --git a/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/services/GetMappaDetailForPersonServiceTest.kt b/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/services/GetMappaDetailForPersonServiceTest.kt new file mode 100644 index 000000000..b7991894e --- /dev/null +++ b/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/services/GetMappaDetailForPersonServiceTest.kt @@ -0,0 +1,102 @@ +package uk.gov.justice.digital.hmpps.hmppsintegrationapi.services + +import io.kotest.core.spec.style.DescribeSpec +import io.kotest.matchers.shouldBe +import org.mockito.Mockito +import org.mockito.internal.verification.VerificationModeFactory +import org.mockito.kotlin.verify +import org.mockito.kotlin.whenever +import org.springframework.boot.test.context.ConfigDataApplicationContextInitializer +import org.springframework.boot.test.mock.mockito.MockBean +import org.springframework.test.context.ContextConfiguration +import uk.gov.justice.digital.hmpps.hmppsintegrationapi.gateways.NDeliusGateway +import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.Identifiers +import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.MappaDetail +import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.Person +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 + +@ContextConfiguration( + initializers = [ConfigDataApplicationContextInitializer::class], + classes = [GetMappaDetailForPersonService::class], +) +internal class GetMappaDetailForPersonServiceTest( + @MockBean val getPersonService: GetPersonService, + @MockBean val nDeliusGateway: NDeliusGateway, + private val getMappaDetailForPersonService: GetMappaDetailForPersonService, +) : DescribeSpec( + { + val hmppsId = "1234/56789B" + val deliusCrn = "X123456" + + val personFromProbationOffenderSearch = + Person(firstName = "Phoebe", lastName = "Buffay", identifiers = Identifiers(deliusCrn = deliusCrn)) + + val mappaDetailForPerson = MappaDetail( + level = 1, + levelDescription = "string", + category = 1, + categoryDescription = "string", + startDate = "string", + reviewDate = "string", + notes = "string", + ) + + beforeEach { + Mockito.reset(getPersonService) + Mockito.reset(nDeliusGateway) + + whenever(getPersonService.execute(hmppsId = hmppsId)).thenReturn( + Response( + data = personFromProbationOffenderSearch, + ), + ) + + whenever(nDeliusGateway.getMappaDetailForPerson(deliusCrn)).thenReturn( + Response( + data = mappaDetailForPerson, + ), + ) + } + + it("Returns mappa detail for person given a hmppsId") { + whenever(getPersonService.execute(hmppsId = hmppsId)).thenReturn( + Response( + data = personFromProbationOffenderSearch, + ), + ) + + val result = getMappaDetailForPersonService.execute(hmppsId) + + result.shouldBe(Response(data = mappaDetailForPerson)) + } + + it("gets a person using a Hmpps ID") { + getMappaDetailForPersonService.execute(hmppsId) + + verify(getPersonService, VerificationModeFactory.times(1)).execute(hmppsId = hmppsId) + } + + describe("when an upstream API returns an error when looking up a person from a Hmpps ID") { + beforeEach { + whenever(getPersonService.execute(hmppsId = hmppsId)).thenReturn( + Response( + data = null, + errors = listOf( + UpstreamApiError( + causedBy = UpstreamApi.PROBATION_OFFENDER_SEARCH, + type = UpstreamApiError.Type.ENTITY_NOT_FOUND, + ), + ), + ), + ) + } + + it("does not get mappa detail from delius") { + getMappaDetailForPersonService.execute(hmppsId) + verify(nDeliusGateway, VerificationModeFactory.times(0)).getOffencesForPerson(id = deliusCrn) + } + } + }, +) diff --git a/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/smoke/person/RisksSmokeTest.kt b/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/smoke/person/RisksSmokeTest.kt index e90ba1e0e..8287cfb2f 100644 --- a/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/smoke/person/RisksSmokeTest.kt +++ b/src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/smoke/person/RisksSmokeTest.kt @@ -89,6 +89,27 @@ class RisksSmokeTest : DescribeSpec( ) } + it("return mappa detail for a person") { + val response = httpClient.performAuthorised("$basePath/mappadetail") + + response.statusCode().shouldBe(HttpStatus.OK.value()) + response.body().shouldEqualJson( + """ + { + "data": { + "level": -2147483648, + "levelDescription": "string", + "category": -2147483648, + "categoryDescription": "string", + "startDate": "2019-08-24", + "reviewDate": "2019-08-24", + "notes": "string" + } + } + """.removeWhitespaceAndNewlines(), + ) + } + it("returns rosh risks for a person") { val response = httpClient.performAuthorised(basePath)