Skip to content

Commit

Permalink
ADJST-884 Retrieve the history of imprisonment status for an offender (
Browse files Browse the repository at this point in the history
…#2304)

* ADJST-884 Retrieve the history of an inmates status.

* ADJST-844 Addressing review comments.
  • Loading branch information
ldlharper authored Dec 3, 2024
1 parent 1faa175 commit f014375
Show file tree
Hide file tree
Showing 7 changed files with 225 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package uk.gov.justice.hmpps.prison.api.model.imprisonmentstatus

import com.fasterxml.jackson.annotation.JsonInclude
import io.swagger.v3.oas.annotations.media.Schema
import java.time.LocalDate

@Schema(description = "Represents an offenders imprisonment status at a point in history")
@JsonInclude(JsonInclude.Include.NON_NULL)
data class ImprisonmentStatusHistoryDto(
@Schema(description = "The imprisonment status")
val status: String,

@Schema(description = "The date the status was effective from")
val effectiveDate: LocalDate,

@Schema(description = "The agency the status was set by")
val agencyId: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package uk.gov.justice.hmpps.prison.api.resource

import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.Parameter
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.responses.ApiResponses
import io.swagger.v3.oas.annotations.tags.Tag
import lombok.extern.slf4j.Slf4j
import org.springframework.validation.annotation.Validated
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.hmpps.prison.api.model.ErrorResponse
import uk.gov.justice.hmpps.prison.api.model.imprisonmentstatus.ImprisonmentStatusHistoryDto
import uk.gov.justice.hmpps.prison.security.VerifyOffenderAccess
import uk.gov.justice.hmpps.prison.service.imprisonmentstatus.ImprisonmentStatusHistoryService

@Slf4j
@RestController
@Tag(name = "imprisonment-status-history")
@Validated
@RequestMapping(
value = ["\${api.base.path}/imprisonment-status-history"],
produces = ["application/json"],
)
class ImprisonmentStatusHistoryResource(private val imprisonmentStatusHistoryService: ImprisonmentStatusHistoryService) {

@ApiResponses(
ApiResponse(
responseCode = "200",
description = "The imprisonment status history.",
content = [
Content(
mediaType = "application/json",
schema = Schema(implementation = ImprisonmentStatusHistoryDto::class),
),
],
),
ApiResponse(
responseCode = "404",
description = "Requested resource not found.",
content = [Content(mediaType = "application/json", schema = Schema(implementation = ErrorResponse::class))],
),
)
@Operation(summary = "Returns the details of all the historic imprisonment statuses for an offender.")
@GetMapping("/{offenderNo}")
@VerifyOffenderAccess(overrideRoles = ["GLOBAL_SEARCH", "VIEW_PRISONER_DATA"])
fun getImprisonmentStatusHistory(
@PathVariable("offenderNo") @Parameter(
description = "The required offender id (mandatory)",
required = true,
) offenderNo: String,
): List<ImprisonmentStatusHistoryDto> {
return imprisonmentStatusHistoryService.getImprisonmentStatusHistory(offenderNo)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import lombok.With;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.Hibernate;
import org.hibernate.type.YesNoConverter;
Expand All @@ -29,6 +30,7 @@
@Entity
@Table(name = "IMPRISONMENT_STATUSES")
@ToString(of = { "id", "status", "description"})
@With
public class ImprisonmentStatus extends AuditableEntity {

@Id
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package uk.gov.justice.hmpps.prison.repository.jpa.repository;

import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import uk.gov.justice.hmpps.prison.repository.jpa.model.OffenderImprisonmentStatus;
import uk.gov.justice.hmpps.prison.repository.jpa.model.OffenderImprisonmentStatus.PK;

import java.util.List;

public interface OffenderImprisonmentStatusRepository extends CrudRepository<OffenderImprisonmentStatus, PK> {

@Query("""
select ois
from OffenderImprisonmentStatus ois
join ois.offenderBooking ob
join ob.offender o
join fetch ois.imprisonmentStatus is
where o.nomsId = :offenderId
"""
)
List<OffenderImprisonmentStatus> findByOffender(String offenderId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package uk.gov.justice.hmpps.prison.service.imprisonmentstatus

import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import uk.gov.justice.hmpps.prison.api.model.imprisonmentstatus.ImprisonmentStatusHistoryDto
import uk.gov.justice.hmpps.prison.repository.jpa.repository.OffenderImprisonmentStatusRepository

@Service
@Transactional(readOnly = true)
class ImprisonmentStatusHistoryService(
private val offenderImprisonmentStatusRepository: OffenderImprisonmentStatusRepository,
) {

fun getImprisonmentStatusHistory(offenderNo: String): List<ImprisonmentStatusHistoryDto> {
return offenderImprisonmentStatusRepository.findByOffender(offenderNo)
.groupBy { it.effectiveDate }
.map { (_, statuses) -> statuses.maxBy { it.imprisonStatusSeq } }
.map {
ImprisonmentStatusHistoryDto(
status = it.imprisonmentStatus.status,
effectiveDate = it.effectiveDate,
agencyId = it.agyLocId,
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package uk.gov.justice.hmpps.prison.api.resource.impl

import org.junit.jupiter.api.Test
import org.springframework.http.MediaType

class ImprisonmentStatusHistoryResourceImplTest : ResourceTest() {
@Test
fun courtDateResults() {
webTestClient.get()
.uri("/api/imprisonment-status-history/{offenderNo}", "A1180HL")
.headers(setAuthorisation(listOf("ROLE_VIEW_PRISON_DATA")))
.accept(MediaType.APPLICATION_JSON)
.exchange()
.expectBody()
.jsonPath("$.length()").isEqualTo(3)
.jsonPath("[0].status").isEqualTo("FTR_ORA")
.jsonPath("[0].effectiveDate").isEqualTo("2016-03-29")
.jsonPath("[0].agencyId").isEqualTo("MDI")
.jsonPath("[1].status").isEqualTo("TRL")
.jsonPath("[1].effectiveDate").isEqualTo("2016-03-30")
.jsonPath("[1].agencyId").isEqualTo("MDI")
.jsonPath("[2].status").isEqualTo("DPP")
.jsonPath("[2].effectiveDate").isEqualTo("2016-03-31")
.jsonPath("[2].agencyId").isEqualTo("MDI")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package uk.gov.justice.hmpps.prison.service.imprisonmentstatus

import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.mockito.kotlin.mock
import org.mockito.kotlin.whenever
import uk.gov.justice.hmpps.prison.api.model.imprisonmentstatus.ImprisonmentStatusHistoryDto
import uk.gov.justice.hmpps.prison.repository.jpa.model.ImprisonmentStatus
import uk.gov.justice.hmpps.prison.repository.jpa.model.OffenderImprisonmentStatus
import uk.gov.justice.hmpps.prison.repository.jpa.repository.OffenderImprisonmentStatusRepository
import java.time.LocalDate

class ImprisonmentStatusHistoryServiceTest {

private val offenderImprisonmentStatusRepository = mock<OffenderImprisonmentStatusRepository>()
private val imprisonmentStatusHistoryService = ImprisonmentStatusHistoryService(
offenderImprisonmentStatusRepository,
)

@Test
fun getInmateStatusHistory() {
val offenderId = "ABC123"
val remandStatus = ImprisonmentStatus().withStatus("SEC38")
val sentencedStatus = ImprisonmentStatus().withStatus("ADIMP_ORA20")
val recallStatus = ImprisonmentStatus().withStatus("LR")
val firstDate = LocalDate.of(2024, 1, 1)
val secondDate = LocalDate.of(2024, 2, 1)
whenever(offenderImprisonmentStatusRepository.findByOffender(offenderId)).thenReturn(
listOf(
OffenderImprisonmentStatus()
.withImprisonmentStatus(sentencedStatus)
.withEffectiveDate(firstDate)
.withImprisonStatusSeq(1)
.withAgyLocId("KMI"),
OffenderImprisonmentStatus()
.withImprisonmentStatus(remandStatus)
.withEffectiveDate(firstDate)
.withImprisonStatusSeq(2)
.withAgyLocId("KMI"),
OffenderImprisonmentStatus()
.withImprisonmentStatus(recallStatus)
.withEffectiveDate(secondDate)
.withImprisonStatusSeq(3)
.withAgyLocId("BMI"),
OffenderImprisonmentStatus()
.withImprisonmentStatus(sentencedStatus)
.withEffectiveDate(secondDate)
.withImprisonStatusSeq(4)
.withAgyLocId("BMI"),
),
)

val result = imprisonmentStatusHistoryService.getImprisonmentStatusHistory(offenderId)

assertThat(
result,
).isEqualTo(
listOf(
ImprisonmentStatusHistoryDto(
status = "SEC38",
effectiveDate = firstDate,
agencyId = "KMI",
),
ImprisonmentStatusHistoryDto(
status = "ADIMP_ORA20",
effectiveDate = secondDate,
agencyId = "BMI",
),
),
)
}
}

0 comments on commit f014375

Please sign in to comment.