Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HIA-697 - Thin Slice for Prison Office Manager #400

Merged
merged 20 commits into from
Apr 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Dockerfile.setup-manage-pom-case-api
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
FROM node:current-alpine3.17

RUN apk update && apk add bash curl

RUN curl https://allocation-manager-staging.apps.live.cloud-platform.service.justice.gov.uk/v3/api-docs.json > manage-pom-case-api.json && \
npm install -g @stoplight/prism-cli

CMD prism mock -p 4010 -h 0.0.0.0 /manage-pom-case-api.json
12 changes: 12 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ services:
condition: service_healthy
probation-integration-epf-api:
condition: service_healthy
manage-pom-case-api:
condition: service_healthy
environment:
- SERVER_PORT=8080
- SPRING_PROFILES_ACTIVE=local-docker
Expand Down Expand Up @@ -124,6 +126,16 @@ services:
ports:
- '4080:4010'

manage-pom-case-api:
build:
context: .
dockerfile: Dockerfile.setup-manage-pom-case-api
container_name: manage-pom-case-api
healthcheck:
test: 'wget --header="Authorization: Bearer abc" http://127.0.0.1:4010/api/allocation/X1234YZ/primary_pom -O /dev/null'
ports:
- '4090:4010'

local-stack-aws:
image: localstack/localstack:3.0
container_name: local-stack-aws
Expand Down
96 changes: 95 additions & 1 deletion openapi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,40 @@ paths:
NoQueryParametersBadRequestError:
$ref: "#/components/examples/InternalServerError"

/v1/persons/{HmppsId}/person-responsible-officer:
get:
summary: Returns the person responsible officer associated with a person.
parameters:
- $ref: "#/components/parameters/HmppsId"
responses:
"200":
description: Successfully found the person responsible officer for a person with the provided HMPPS ID.
content:
application/json:
schema:
type: object
properties:
data:
$ref: "#/components/schemas/PersonResponsibleOfficer"
"404":
description: Failed to find licenses for a person with the provided HMPPS ID.
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
examples:
PersonNotFoundError:
$ref: "#/components/examples/PersonNotFoundError"
"500":
description: An upstream service was not responding, so we cannot verify the accuracy of any data we did get.
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
examples:
NoQueryParametersBadRequestError:
$ref: "#/components/examples/InternalServerError"

/v1/persons/{HmppsId}/licences/conditions:
get:
summary: Returns license conditions associated with a person.
Expand Down Expand Up @@ -1269,6 +1303,19 @@ components:
releaseDate:
type: string
format: date
CommunityOffenderManager:
type: object
properties:
name:
$ref: "#/components/schemas/PersonResponsibleOfficerName"
email:
type: string
nullable: true
telephoneNumber:
type: string
nullable: true
team:
$ref: "#/components/schemas/PersonResponsibleOfficerTeam"
ContactDetails:
properties:
phoneNumbers:
Expand Down Expand Up @@ -1755,6 +1802,30 @@ components:
description: Currently a hmppsId is a CRN identifier however this will change in the future to be a new unique Hmpps identifier
contactDetails:
$ref: "#/components/schemas/ContactDetails"
PersonResponsibleOfficerName:
type: object
properties:
forename:
type: string
nullable: true
surname:
type: string
nullable: true
PersonResponsibleOfficerTeam:
type: object
properties:
code:
type: string
nullable: true
description:
type: string
nullable: true
email:
type: string
nullable: true
telephoneNumber:
type: string
nullable: true
PhoneNumbers:
type: array
items:
Expand All @@ -1768,6 +1839,13 @@ components:
type: string
example: "TELEPHONE"
description: "The type of number"
PersonResponsibleOfficer:
type: object
properties:
prisonOffenderOfficer:
$ref: "#/components/schemas/PrisonOffenderOfficer"
communityOffenderManager:
$ref: "#/components/schemas/CommunityOffenderManager"
PersonLicencesData:
type: object
properties:
Expand Down Expand Up @@ -1839,7 +1917,23 @@ components:
minItems: 0
items:
$ref: "#/components/schemas/ReasonableAdjustment"

Prison:
type: object
properties:
code:
type: string
nullable: true
PrisonOffenderOfficer:
type: object
properties:
forename:
type: string
nullable: true
surname:
type: string
nullable: true
prison:
$ref: "#/components/schemas/Prison"

Punishment:
type: object
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
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.PersonResponsibleOfficer
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.UpstreamApiError
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.services.GetCommunityOffenderManagerForPersonService
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.services.GetPrisonOffenderManagerForPersonService
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.services.internal.AuditService

@RestController
@RequestMapping("/v1/persons")
class PersonResponsibleOfficerController(
@Autowired val auditService: AuditService,
@Autowired val getPrisonOffenderManagerForPersonService: GetPrisonOffenderManagerForPersonService,
@Autowired val getCommunityOffenderManagerForPersonService: GetCommunityOffenderManagerForPersonService,
) {
@GetMapping("{encodedHmppsId}/person-responsible-officer")
fun getPersonResponsibleOfficer(
@PathVariable encodedHmppsId: String,
): Map<String, PersonResponsibleOfficer> {
val hmppsId = encodedHmppsId.decodeUrlCharacters()
val prisonOffenderManager = getPrisonOffenderManagerForPersonService.execute(hmppsId)
val communityOffenderManager = getCommunityOffenderManagerForPersonService.execute(hmppsId)

if (prisonOffenderManager.hasError(UpstreamApiError.Type.ENTITY_NOT_FOUND)) {
throw EntityNotFoundException("Could not find prison offender manager related to id: $hmppsId")
}

if (communityOffenderManager.hasError(UpstreamApiError.Type.ENTITY_NOT_FOUND)) {
throw EntityNotFoundException("Could not find community offender manager related to id: $hmppsId")
}

val mergedData =
PersonResponsibleOfficer(
prisonOffenderManager = prisonOffenderManager.data,
communityOffenderManager = communityOffenderManager.data,
)

auditService.createEvent("GET_PERSON_RESPONSIBLE_OFFICER", mapOf("hmppsId" to hmppsId))
return mapOf("data" to mergedData)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package uk.gov.justice.digital.hmpps.hmppsintegrationapi.gateways

import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
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.models.hmpps.PrisonOffenderManager
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.managePOMCase.AllocationPrimaryPOM

@Component
class ManagePOMCaseGateway(
@Value("\${services.manage-pom-case-api.base-url}") baseUrl: String,
) {
private val webClient = WebClientWrapper(baseUrl)

@Autowired
lateinit var hmppsAuthGateway: HmppsAuthGateway

fun getPrimaryPOMForNomisNumber(id: String): Response<PrisonOffenderManager> {
val result =
webClient.request<AllocationPrimaryPOM>(
HttpMethod.GET,
"/api/allocation/$id/primary_pom",
authenticationHeader(),
UpstreamApi.MANAGE_POM_CASE,
)

return when (result) {
is WebClientWrapper.WebClientWrapperResponse.Success -> {
Response(data = result.data.toPrisonOffenderManager())
}

is WebClientWrapper.WebClientWrapperResponse.Error -> {
Response(
data = PrisonOffenderManager(),
errors = result.errors,
)
}
}
}

private fun authenticationHeader(): Map<String, String> {
val token = hmppsAuthGateway.getClientToken("ManagePOMCase")

return mapOf(
"Authorization" to "Bearer $token",
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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.CommunityOffenderManager
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
Expand Down Expand Up @@ -91,6 +92,28 @@ class NDeliusGateway(
}
}

fun getCommunityOffenderManagerForPerson(id: String): Response<CommunityOffenderManager> {
val result =
webClient.request<NDeliusSupervisions>(
HttpMethod.GET,
"/case/$id/supervisions",
authenticationHeader(),
UpstreamApi.NDELIUS,
)
return when (result) {
is WebClientWrapperResponse.Success -> {
Response(data = result.data.communityManager.toCommunityOffenderManager())
}

is WebClientWrapperResponse.Error -> {
Response(
data = CommunityOffenderManager(),
errors = result.errors,
)
}
}
}

private fun authenticationHeader(): Map<String, String> {
val token = hmppsAuthGateway.getClientToken("nDelius")

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps

data class CommunityOffenderManager(
val name: PersonResponsibleOfficerName = PersonResponsibleOfficerName(),
val email: String? = null,
val telephoneNumber: String? = null,
val team: PersonResponsibleOfficerTeam = PersonResponsibleOfficerTeam(),
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps

data class PersonResponsibleOfficer(
val prisonOffenderManager: PrisonOffenderManager = PrisonOffenderManager(),
val communityOffenderManager: CommunityOffenderManager = CommunityOffenderManager(),
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps

data class PersonResponsibleOfficerName(
val forename: String? = null,
val surname: String? = null,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps

data class PersonResponsibleOfficerTeam(
val code: String? = null,
val description: String? = null,
val email: String? = null,
val telephoneNumber: String? = null,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps

data class Prison(
val code: String? = null,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps

data class PrisonOffenderManager(
val forename: String? = null,
val surname: String? = null,
val prison: Prison = Prison(),
)
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ enum class UpstreamApi {
ADJUDICATIONS,
CVL,
CASE_NOTES,
MANAGE_POM_CASE,
TEST,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.managePOMCase

data class AllocationManager(
val code: Int? = null,
val forename: String? = null,
val surname: String? = null,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.managePOMCase

import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.Prison
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.PrisonOffenderManager

data class AllocationPrimaryPOM(
val manager: AllocationManager = AllocationManager(),
val prison: AllocationPrison = AllocationPrison(),
) {
fun toPrisonOffenderManager(): PrisonOffenderManager =
PrisonOffenderManager(
forename = this.manager.forename,
surname = this.manager.surname,
prison =
Prison(
code = this.prison.code,
),
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.managePOMCase

data class AllocationPrison(
val code: String? = null,
)
Loading
Loading