Skip to content

Commit 7b973b0

Browse files
committed
Updated transaction endpoint uri signature, added associated unit tests
1 parent 843c035 commit 7b973b0

File tree

7 files changed

+99
-6
lines changed

7 files changed

+99
-6
lines changed

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

+20-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import io.swagger.v3.oas.annotations.Operation
44
import io.swagger.v3.oas.annotations.Parameter
55
import io.swagger.v3.oas.annotations.media.Content
66
import io.swagger.v3.oas.annotations.responses.ApiResponse
7+
import io.swagger.v3.oas.annotations.tags.Tag
78
import jakarta.validation.ValidationException
89
import org.springframework.beans.factory.annotation.Autowired
910
import org.springframework.web.bind.annotation.GetMapping
@@ -14,18 +15,22 @@ import org.springframework.web.bind.annotation.RequestParam
1415
import org.springframework.web.bind.annotation.RestController
1516
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.exception.EntityNotFoundException
1617
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.DataResponse
18+
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.Transaction
1719
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.Transactions
1820
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.UpstreamApiError
1921
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.roleconfig.ConsumerFilters
22+
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.services.GetTransactionForPersonService
2023
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.services.GetTransactionsForPersonService
2124
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.services.internal.AuditService
2225
import java.time.LocalDate
2326

2427
@RestController
2528
@RequestMapping("/v1/prison/{prisonId}/prisoners/{hmppsId}")
29+
@Tag(name = "prison")
2630
class TransactionsController(
2731
@Autowired val auditService: AuditService,
2832
@Autowired val getTransactionsForPersonService: GetTransactionsForPersonService,
33+
@Autowired val getTransactionForPersonService: GetTransactionForPersonService,
2934
) {
3035
@Operation(
3136
summary = "Returns all transactions for a prisoner associated with an account code that they have at a prison.",
@@ -138,11 +143,24 @@ class TransactionsController(
138143
),
139144
],
140145
)
141-
@GetMapping("/accounts/{clientUniqueRef}/transactions")
146+
@GetMapping("/transactions/{clientUniqueRef}")
142147
fun getTransactionsByClientUniqueRef(
143148
@PathVariable prisonId: String,
144149
@PathVariable hmppsId: String,
145150
@PathVariable clientUniqueRef: String,
146151
@RequestAttribute filters: ConsumerFilters?,
147-
): DataResponse<Transactions?> = DataResponse(null)
152+
): DataResponse<Transaction?> {
153+
val response = getTransactionForPersonService.execute(hmppsId, prisonId, clientUniqueRef, filters)
154+
155+
if (response.hasError(UpstreamApiError.Type.ENTITY_NOT_FOUND)) {
156+
throw EntityNotFoundException("Could not find transaction with id: $hmppsId")
157+
}
158+
159+
if (response.hasError(UpstreamApiError.Type.BAD_REQUEST)) {
160+
throw ValidationException("Either invalid HMPPS ID: $hmppsId at or incorrect prison: $prisonId")
161+
}
162+
163+
auditService.createEvent("GET_TRANSACTION_FOR_PERSON", mapOf("hmppsId" to hmppsId, "prisonId" to prisonId, "clientUniqueRef" to clientUniqueRef))
164+
return DataResponse(response.data)
165+
}
148166
}

src/main/resources/application-dev.yml

+3
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ authorisation:
131131
- "/v1/prison/.*/prisoners/[^/]*/balances$"
132132
- "/v1/prison/.*/prisoners/.*/accounts/.*/balances"
133133
- "/v1/prison/.*/prisoners/.*/accounts/.*/transactions"
134+
- "/v1/prison/.*/prisoners/.*/transactions/[^/]*$"
134135
filters:
135136
kilco:
136137
include:
@@ -141,6 +142,7 @@ authorisation:
141142
- "/v1/prison/.*/prisoners/[^/]*/balances$"
142143
- "/v1/prison/.*/prisoners/.*/accounts/.*/balances"
143144
- "/v1/prison/.*/prisoners/.*/accounts/.*/transactions"
145+
- "/v1/prison/.*/prisoners/.*/transactions/[^/]*$"
144146
filters:
145147
meganexus:
146148
include:
@@ -159,6 +161,7 @@ authorisation:
159161
- "/v1/prison/.*/prisoners/[^/]*/balances$"
160162
- "/v1/prison/.*/prisoners/.*/accounts/.*/balances"
161163
- "/v1/prison/.*/prisoners/.*/accounts/.*/transactions"
164+
- "/v1/prison/.*/prisoners/.*/transactions/[^/]*$"
162165
filters:
163166
serco:
164167
include:

src/main/resources/application-integration-test.yml

+1
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ authorisation:
8787
- "/v1/prison/.*/prisoners/[^/]*/balances$"
8888
- "/v1/prison/.*/prisoners/.*/accounts/.*/balances"
8989
- "/v1/prison/.*/prisoners/.*/accounts/.*/transactions"
90+
- "/v1/prison/.*/prisoners/.*/transactions/[^/]*$"
9091
filters:
9192
config-test:
9293
include:

src/main/resources/application-local-docker.yml

+1
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ authorisation:
6161
- "/v1/prison/.*/prisoners/[^/]*/balances$"
6262
- "/v1/prison/.*/prisoners/.*/accounts/.*/balances"
6363
- "/v1/prison/.*/prisoners/.*/accounts/.*/transactions"
64+
- "/v1/prison/.*/prisoners/.*/transactions/[^/]*$"
6465
filters:
6566
config-test:
6667
include:

src/main/resources/application-local.yml

+1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ authorisation:
6868
- "/v1/prison/.*/prisoners/[^/]*/balances$"
6969
- "/v1/prison/.*/prisoners/.*/accounts/.*/balances"
7070
- "/v1/prison/.*/prisoners/.*/accounts/.*/transactions"
71+
- "/v1/prison/.*/prisoners/.*/transactions/[^/]*$"
7172
filters:
7273
config-test:
7374
include:

src/main/resources/application-test.yml

+1
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ authorisation:
8989
- "/v1/prison/.*/prisoners/[^/]*/balances$"
9090
- "/v1/prison/.*/prisoners/.*/accounts/.*/balances"
9191
- "/v1/prison/.*/prisoners/.*/accounts/.*/transactions"
92+
- "/v1/prison/.*/prisoners/.*/transactions/[^/]*$"
9293
config-test:
9394
include:
9495
- "/v1/config/authorisation"

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

+72-4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.Transaction
2020
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.Type
2121
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.UpstreamApi
2222
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.models.hmpps.UpstreamApiError
23+
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.services.GetTransactionForPersonService
2324
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.services.GetTransactionsForPersonService
2425
import uk.gov.justice.digital.hmpps.hmppsintegrationapi.services.internal.AuditService
2526
import java.time.LocalDate
@@ -30,15 +31,16 @@ class TransactionsControllerTest(
3031
@Autowired var springMockMvc: MockMvc,
3132
@MockitoBean val auditService: AuditService,
3233
@MockitoBean val getTransactionsForPersonService: GetTransactionsForPersonService,
34+
@MockitoBean val getTransactionForPersonService: GetTransactionForPersonService,
3335
) : DescribeSpec(
3436
{
3537
val hmppsId = "200313116M"
3638
val prisonId = "ABC"
3739
val accountCode = "spends"
38-
val clientUniqueRef = "client_unique_ref"
40+
val clientUniqueRef = "ABC123456X"
3941
val basePath = "/v1/prison/$prisonId/prisoners/$hmppsId"
4042
val transactionsPath = "$basePath/accounts/$accountCode/transactions"
41-
val transactionPath = "$basePath/accounts/$clientUniqueRef/transactions"
43+
val transactionPath = "$basePath/transactions/$clientUniqueRef"
4244
val mockMvc = IntegrationAPIMockMvc(springMockMvc)
4345

4446
val transactions =
@@ -55,7 +57,15 @@ class TransactionsControllerTest(
5557
),
5658
)
5759

58-
it("calls the service with expected parameters when supplied a date range") {
60+
val transaction =
61+
Transaction(
62+
id = "123",
63+
type = Type(code = "spends", desc = "Spends"),
64+
amount = 100,
65+
date = "2016-10-21",
66+
description = "Spends desc",
67+
)
68+
it("calls the transactions service with expected parameters when supplied a date range") {
5969
val dateParams = "?from_date=2025-01-01&to_date=2025-01-01"
6070
mockMvc.performAuthorised(transactionsPath + dateParams)
6171

@@ -123,7 +133,65 @@ class TransactionsControllerTest(
123133
),
124134
)
125135
val dateParams = "?from_date=2025-01-01&to_date=2025-01-01"
126-
val result = mockMvc.performAuthorised(basePath + dateParams)
136+
val result = mockMvc.performAuthorised(transactionsPath + dateParams)
137+
138+
result.response.status.shouldBe(HttpStatus.BAD_REQUEST.value())
139+
}
140+
141+
// get Transaction
142+
it("returns a prisoner's transaction according to clientUniqueRef") {
143+
whenever(getTransactionForPersonService.execute(hmppsId, prisonId, clientUniqueRef, null)).thenReturn(Response(transaction))
144+
145+
val result = mockMvc.performAuthorised(transactionPath)
146+
147+
result.response.contentAsString.shouldContain(
148+
"""
149+
{
150+
"id": "123",
151+
"type": {
152+
"code": "spends",
153+
"desc": "Spends"
154+
},
155+
"description": "Spends desc",
156+
"amount": 100,
157+
"date": "2016-10-21"
158+
}
159+
""".removeWhitespaceAndNewlines(),
160+
)
161+
}
162+
163+
it("returns a 404 NOT FOUND status code when could not find the transaction") {
164+
whenever(getTransactionForPersonService.execute(hmppsId, prisonId, clientUniqueRef, null)).thenReturn(
165+
Response(
166+
data = null,
167+
errors =
168+
listOf(
169+
UpstreamApiError(
170+
causedBy = UpstreamApi.NOMIS,
171+
type = UpstreamApiError.Type.ENTITY_NOT_FOUND,
172+
),
173+
),
174+
),
175+
)
176+
val result = mockMvc.performAuthorised(transactionPath)
177+
178+
result.response.status.shouldBe(HttpStatus.NOT_FOUND.value())
179+
}
180+
181+
it("returns a 400 BAD REQUEST status code when there is an invalid HMPPS ID or incorrect prison, to get a singular transaction") {
182+
whenever(getTransactionForPersonService.execute(hmppsId, prisonId, clientUniqueRef, null)).thenReturn(
183+
Response(
184+
data = null,
185+
errors =
186+
listOf(
187+
UpstreamApiError(
188+
causedBy = UpstreamApi.NOMIS,
189+
type = UpstreamApiError.Type.BAD_REQUEST,
190+
),
191+
),
192+
),
193+
)
194+
val result = mockMvc.performAuthorised(transactionPath)
127195

128196
result.response.status.shouldBe(HttpStatus.BAD_REQUEST.value())
129197
}

0 commit comments

Comments
 (0)