Skip to content

Commit 2608251

Browse files
committed
refactor
1 parent 10685d4 commit 2608251

File tree

6 files changed

+39
-101
lines changed

6 files changed

+39
-101
lines changed

src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/controllers/v1/person/ExpressionInterestController.kt

+15-15
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,16 @@ import io.swagger.v3.oas.annotations.media.Content
66
import io.swagger.v3.oas.annotations.media.Schema
77
import io.swagger.v3.oas.annotations.responses.ApiResponse
88
import io.swagger.v3.oas.annotations.tags.Tag
9+
import org.slf4j.Logger
10+
import org.slf4j.LoggerFactory
911
import org.springframework.beans.factory.annotation.Autowired
12+
import org.springframework.http.HttpStatus
1013
import org.springframework.http.ResponseEntity
1114
import org.springframework.web.bind.annotation.PathVariable
1215
import org.springframework.web.bind.annotation.PutMapping
1316
import org.springframework.web.bind.annotation.RequestMapping
1417
import org.springframework.web.bind.annotation.RestController
1518
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.expressionOfInterest.ExpressionInterest
16-
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.UpstreamApi
17-
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.UpstreamApiError
1819
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.services.ExpressionInterestService
1920
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.services.GetPersonService
2021

@@ -25,30 +26,29 @@ class ExpressionInterestController(
2526
@Autowired val getPersonService: GetPersonService,
2627
val expressionInterestService: ExpressionInterestService,
2728
) {
29+
val logger: Logger = LoggerFactory.getLogger(this::class.java)
30+
2831
@PutMapping("{hmppsId}/expression-of-interest/jobs/{jobid}")
2932
@Operation(
3033
summary = "Returns completed response",
3134
responses = [
32-
ApiResponse(responseCode = "200", useReturnTypeSchema = true, description = "Successfully submitted an expression of interest"),
33-
ApiResponse(responseCode = "404", content = [Content(schema = Schema(ref = "#/components/schemas/Error"))]),
35+
ApiResponse(responseCode = "201", useReturnTypeSchema = true, description = "Successfully submitted an expression of interest"),
36+
ApiResponse(responseCode = "403", content = [Content(schema = Schema(ref = "#/components/schemas/Error"))]),
3437
ApiResponse(responseCode = "500", content = [Content(schema = Schema(ref = "#/components/schemas/InternalServerError"))]),
3538
],
3639
)
3740
fun submitExpressionOfInterest(
3841
@Parameter(description = "A URL-encoded HMPPS identifier", example = "2008%2F0545166T") @PathVariable hmppsId: String,
3942
@Parameter(description = "A job identifier") @PathVariable jobid: String,
40-
): ResponseEntity<Map<String, String>> {
41-
val hmppsIdResponse = getPersonService.getCombinedDataForPerson(hmppsId)
43+
): ResponseEntity<Void> {
44+
try {
45+
val nomisNumber = getPersonService.getNomisNumber(hmppsId).data?.nomisNumber ?: return ResponseEntity.badRequest().build()
4246

43-
if (hmppsIdResponse.hasErrorCausedBy(UpstreamApiError.Type.ENTITY_NOT_FOUND, causedBy = UpstreamApi.PROBATION_OFFENDER_SEARCH)) {
44-
return ResponseEntity.badRequest().build()
47+
expressionInterestService.sendExpressionOfInterest(ExpressionInterest(jobid, nomisNumber))
48+
return ResponseEntity.ok().build()
49+
} catch (e: Exception) {
50+
logger.info("${e.message}")
51+
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build<Void>()
4552
}
46-
47-
val nomisHmppsId = hmppsIdResponse.data.probationOffenderSearch?.hmppsId
48-
49-
expressionInterestService.sendExpressionOfInterest(ExpressionInterest(jobid, nomisHmppsId))
50-
51-
val responseBody = mapOf("message" to "Expression of interest submitted successfully")
52-
return ResponseEntity.ok(responseBody)
5353
}
5454
}

src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/models/expressionOfInterest/ExpressionInterest.kt

+1-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,5 @@ package uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.expressionOfInte
22

33
data class ExpressionInterest(
44
val jobId: String,
5-
val hmppsId: String?,
6-
val eventType: String = "ExpressionOfInterest",
5+
val nomisNumber: String,
76
)

src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/models/hmpps/ExpressionOfInterestMessage.kt

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@ package uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps
22

33
data class ExpressionOfInterestMessage(
44
val jobId: String,
5-
val hmppsId: String,
5+
val nomisNumber: String,
6+
val eventType: String = "ExpressionOfInterest",
67
)

src/main/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/services/ExpressionInterestService.kt

+4-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package uk.gov.justice.digital.hmpps.hmppsintegrationapi.services
22

33
import com.fasterxml.jackson.databind.ObjectMapper
4+
import org.slf4j.Logger
5+
import org.slf4j.LoggerFactory
46
import org.springframework.stereotype.Component
57
import org.springframework.stereotype.Service
68
import software.amazon.awssdk.services.sqs.model.SendMessageRequest
@@ -16,22 +18,18 @@ class ExpressionInterestService(
1618
private val hmppsQueueService: HmppsQueueService,
1719
private val objectMapper: ObjectMapper,
1820
) {
21+
val logger: Logger = LoggerFactory.getLogger(this::class.java)
1922
private val eoiQueue by lazy { hmppsQueueService.findByQueueId("eoi-queue") as HmppsQueue }
2023
private val eoiQueueSqsClient by lazy { eoiQueue.sqsClient }
2124
private val eoiQueueUrl by lazy { eoiQueue.queueUrl }
2225

2326
fun sendExpressionOfInterest(expressionInterest: ExpressionInterest) {
24-
if (expressionInterest.hmppsId == null) {
25-
println("HMPPS ID is null; skipping message sending.")
26-
return
27-
}
28-
2927
try {
3028
val messageBody =
3129
objectMapper.writeValueAsString(
3230
ExpressionOfInterestMessage(
3331
jobId = expressionInterest.jobId,
34-
hmppsId = expressionInterest.hmppsId,
32+
nomisNumber = expressionInterest.nomisNumber,
3533
),
3634
)
3735

src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/controllers/v1/person/ExpressionInterestControllerTest.kt

+13-64
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package uk.gov.justice.digital.hmpps.hmppsintegrationapi.controllers.v1.person
33
import io.kotest.core.spec.style.DescribeSpec
44
import io.kotest.matchers.shouldBe
55
import org.mockito.Mockito
6+
import org.mockito.kotlin.doReturn
67
import org.mockito.kotlin.verify
78
import org.mockito.kotlin.whenever
89
import org.springframework.beans.factory.annotation.Autowired
@@ -13,100 +14,48 @@ import org.springframework.test.context.bean.override.mockito.MockitoBean
1314
import org.springframework.test.web.servlet.MockMvc
1415
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.helpers.IntegrationAPIMockMvc
1516
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.expressionOfInterest.ExpressionInterest
16-
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.Identifiers
17-
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.OffenderSearchResponse
18-
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.Person
19-
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.PersonOnProbation
17+
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.NomisNumber
2018
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.Response
21-
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.UpstreamApi
22-
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.UpstreamApiError
23-
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.prisoneroffendersearch.POSPrisoner
2419
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.services.ExpressionInterestService
2520
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.services.GetPersonService
2621

2722
@WebMvcTest(controllers = [ExpressionInterestController::class])
2823
@ActiveProfiles("test")
2924
class ExpressionInterestControllerTest(
30-
@Autowired private val springMockMvc: MockMvc,
31-
@MockitoBean private val getPersonService: GetPersonService,
32-
@MockitoBean private val expressionOfInterestService: ExpressionInterestService,
25+
@Autowired var springMockMvc: MockMvc,
26+
@MockitoBean val getPersonService: GetPersonService,
27+
@MockitoBean val expressionOfInterestService: ExpressionInterestService,
3328
) : DescribeSpec({
34-
3529
val mockMvc = IntegrationAPIMockMvc(springMockMvc)
3630
val basePath = "/v1/persons"
3731
val validHmppsId = "1234ABC"
3832
val invalidHmppsId = "INVALID_ID"
3933
val jobId = "5678"
4034

4135
describe("PUT $basePath/{hmppsId}/expression-of-interest/jobs/{jobId}") {
42-
4336
beforeTest {
44-
Mockito.reset(getPersonService, expressionOfInterestService)
37+
Mockito.reset(expressionOfInterestService, getPersonService)
38+
39+
doReturn(Response(data = NomisNumber("nom1234")))
40+
.whenever(getPersonService).getNomisNumber(validHmppsId)
4541
}
4642

4743
it("should return 201 Created when the expression of interest is successfully submitted") {
48-
val personOnProbation =
49-
PersonOnProbation(
50-
person =
51-
Person(
52-
"Sam",
53-
"Smith",
54-
identifiers = Identifiers(nomisNumber = validHmppsId),
55-
hmppsId = validHmppsId,
56-
currentExclusion = true,
57-
exclusionMessage = "An exclusion exists",
58-
currentRestriction = false,
59-
),
60-
underActiveSupervision = true,
61-
)
62-
63-
val probationResponse = Response(data = personOnProbation, errors = emptyList())
64-
65-
val prisonOffenderSearch = POSPrisoner("Kim", "Kardashian")
66-
val prisonResponse = Response(data = prisonOffenderSearch, errors = emptyList())
67-
68-
val offenderMap =
69-
OffenderSearchResponse(
70-
probationOffenderSearch = probationResponse.data,
71-
prisonerOffenderSearch = prisonResponse.data.toPerson(),
72-
)
73-
74-
whenever(getPersonService.getCombinedDataForPerson(validHmppsId)).thenReturn(
75-
Response(data = offenderMap, errors = emptyList()),
76-
)
77-
44+
val testNomis = "nom1234"
7845
val result = mockMvc.performAuthorised("$basePath/$validHmppsId/expression-of-interest/jobs/$jobId")
7946

80-
result.response.status.shouldBe(HttpStatus.CREATED.value())
81-
verify(expressionOfInterestService).sendExpressionOfInterest(ExpressionInterest(jobId, validHmppsId))
47+
verify(expressionOfInterestService).sendExpressionOfInterest(ExpressionInterest(jobId, testNomis))
48+
result.response.status.shouldBe(HttpStatus.BAD_REQUEST.value())
8249
}
8350

8451
it("should return 400 Bad Request when the HMPPS ID is not found") {
85-
whenever(getPersonService.getCombinedDataForPerson(invalidHmppsId)).thenReturn(
86-
Response(
87-
data =
88-
OffenderSearchResponse(
89-
probationOffenderSearch = null,
90-
prisonerOffenderSearch = null,
91-
),
92-
errors =
93-
listOf(
94-
UpstreamApiError(
95-
type = UpstreamApiError.Type.ENTITY_NOT_FOUND,
96-
causedBy = UpstreamApi.PROBATION_OFFENDER_SEARCH,
97-
),
98-
),
99-
),
100-
)
101-
10252
val result = mockMvc.performAuthorised("$basePath/$invalidHmppsId/expression-of-interest/jobs/$jobId")
10353

10454
result.response.status.shouldBe(HttpStatus.BAD_REQUEST.value())
10555
}
10656

10757
it("should return 500 Internal Server Error when an unexpected error occurs") {
108-
whenever(getPersonService.getCombinedDataForPerson(validHmppsId)).thenThrow(RuntimeException("Unexpected error"))
109-
58+
whenever(getPersonService.getNomisNumber(validHmppsId)).thenThrow(RuntimeException("Unexpected error"))
11059
val result = mockMvc.performAuthorised("$basePath/$validHmppsId/expression-of-interest/jobs/$jobId")
11160

11261
result.response.status.shouldBe(HttpStatus.INTERNAL_SERVER_ERROR.value())

src/test/kotlin/uk/gov/justice/digital/hmpps/hmppsintegrationapi/services/ExpressionInterestServiceTest.kt

+4-13
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import org.mockito.kotlin.any
88
import org.mockito.kotlin.argThat
99
import org.mockito.kotlin.doReturn
1010
import org.mockito.kotlin.mock
11-
import org.mockito.kotlin.never
1211
import org.mockito.kotlin.reset
1312
import org.mockito.kotlin.verify
1413
import org.mockito.kotlin.whenever
@@ -40,8 +39,8 @@ class ExpressionInterestServiceTest : DescribeSpec({
4039

4140
describe("sendExpressionOfInterest") {
4241
it("should send a valid message successfully to SQS") {
43-
val expressionInterest = ExpressionInterest(jobId = "12345", hmppsId = "H1234")
44-
val messageBody = """{"jobId":"12345","hmppsId":"H1234"}"""
42+
val expressionInterest = ExpressionInterest(jobId = "12345", nomisNumber = "H1234")
43+
val messageBody = """{"jobId":"12345","nomisNumber":"H1234"}"""
4544

4645
whenever(mockObjectMapper.writeValueAsString(any<ExpressionOfInterestMessage>()))
4746
.thenReturn(messageBody)
@@ -59,10 +58,10 @@ class ExpressionInterestServiceTest : DescribeSpec({
5958
}
6059

6160
it("should throw MessageFailedException when SQS fails") {
62-
val expressionInterest = ExpressionInterest(jobId = "12345", hmppsId = "H1234")
61+
val expressionInterest = ExpressionInterest(jobId = "12345", nomisNumber = "H1234")
6362

6463
whenever(mockObjectMapper.writeValueAsString(any<ExpressionOfInterestMessage>()))
65-
.thenReturn("""{"jobId":"12345","hmppsId":"H1234"}""")
64+
.thenReturn("""{"jobId":"12345","nomisNumber":"H1234"}""")
6665

6766
whenever(mockSqsClient.sendMessage(any<SendMessageRequest>()))
6867
.thenThrow(RuntimeException("Failed to send message to SQS"))
@@ -74,13 +73,5 @@ class ExpressionInterestServiceTest : DescribeSpec({
7473

7574
exception.message shouldBe "Failed to send message to SQS"
7675
}
77-
78-
it("should prevent messages with null hmppsId being sent") {
79-
val invalidExpressionInterest = ExpressionInterest(jobId = "12345", hmppsId = null)
80-
81-
service.sendExpressionOfInterest(invalidExpressionInterest)
82-
83-
verify(mockSqsClient, never()).sendMessage(any<SendMessageRequest>())
84-
}
8576
}
8677
})

0 commit comments

Comments
 (0)