diff --git a/projects/court-case-and-delius/src/dev/resources/simulations/__files/get_court_appearances_C123456.json b/projects/court-case-and-delius/src/dev/resources/simulations/__files/get_court_appearances_C123456.json new file mode 100644 index 0000000000..2f92aa56b8 --- /dev/null +++ b/projects/court-case-and-delius/src/dev/resources/simulations/__files/get_court_appearances_C123456.json @@ -0,0 +1,15 @@ +{ + "courtAppearances": [ + { + "courtAppearanceId": 90, + "appearanceDate": "2024-08-06T12:00:00", + "courtCode": "BRMNCC", + "courtName": "Birmingham Crown Court", + "appearanceType": { + "code": "CRN", + "description": "Crown Court" + }, + "crn": "C123456" + } + ] +} \ No newline at end of file diff --git a/projects/court-case-and-delius/src/dev/resources/simulations/mappings/get-convictions.json b/projects/court-case-and-delius/src/dev/resources/simulations/mappings/get-convictions.json index f84fd920d6..1c93da50f5 100644 --- a/projects/court-case-and-delius/src/dev/resources/simulations/mappings/get-convictions.json +++ b/projects/court-case-and-delius/src/dev/resources/simulations/mappings/get-convictions.json @@ -1,5 +1,18 @@ { "mappings": [ + { + "request": { + "method": "GET", + "urlPathTemplate": "/secure/offenders/crn/{crn}/convictions/{convictionId}/courtAppearances" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/json" + }, + "bodyFileName": "get_court_appearances_C123456.json" + } + }, { "request": { "method": "GET", diff --git a/projects/court-case-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/ConvictionByCrnAndEventIdIntegrationTest.kt b/projects/court-case-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/ConvictionByCrnAndEventIdIntegrationTest.kt index 1443a0657d..ffba580394 100644 --- a/projects/court-case-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/ConvictionByCrnAndEventIdIntegrationTest.kt +++ b/projects/court-case-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/ConvictionByCrnAndEventIdIntegrationTest.kt @@ -33,6 +33,7 @@ import uk.gov.justice.digital.hmpps.data.generator.SentenceGenerator.MAIN_OFFENC import uk.gov.justice.digital.hmpps.data.generator.StaffGenerator.ALLOCATED import uk.gov.justice.digital.hmpps.data.generator.UnpaidWorkGenerator.UNPAID_WORK_DETAILS_1 import uk.gov.justice.digital.hmpps.integrations.delius.service.toAttendance +import uk.gov.justice.digital.hmpps.integrations.delius.service.toCourtAppearance import uk.gov.justice.digital.hmpps.test.MockMvcExtensions.contentAsJson import uk.gov.justice.digital.hmpps.test.MockMvcExtensions.withToken import java.time.LocalDate @@ -271,4 +272,17 @@ internal class ConvictionByCrnAndEventIdIntegrationTest { assertThat(response.attendances[0], equalTo(ATTENDANCE_CONTACT_1.toAttendance())) } + + @Test + fun `call convictions by id and courtAppearances`() { + val crn = PersonGenerator.CURRENTLY_MANAGED.crn + val event = SentenceGenerator.CURRENTLY_MANAGED + + val response = mockMvc + .perform(get("/probation-case/$crn/convictions/${event.id}/courtAppearances").withToken()) + .andExpect(status().isOk) + .andReturn().response.contentAsJson() + + assertThat(response.courtAppearances[0], equalTo(COURT_APPEARANCE.toCourtAppearance())) + } } \ No newline at end of file diff --git a/projects/court-case-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/ProxyIntegrationTest.kt b/projects/court-case-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/ProxyIntegrationTest.kt index bd5136e9c7..46c82890b2 100644 --- a/projects/court-case-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/ProxyIntegrationTest.kt +++ b/projects/court-case-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/ProxyIntegrationTest.kt @@ -245,6 +245,10 @@ internal class ProxyIntegrationTest { }, "CONVICTION_BY_ID_PSS": { "convictionId": "?" + }, + "CONVICTION_BY_ID_COURT_APPEARANCES": { + "convictionId": "?", + "activeOnly": true } } } @@ -253,7 +257,7 @@ internal class ProxyIntegrationTest { .withToken() ).andExpect(status().is2xxSuccessful).andReturn().response.contentAsJson() - assertThat(res.totalNumberOfRequests, equalTo(10)) + assertThat(res.totalNumberOfRequests, equalTo(11)) assertThat(res.totalNumberOfCrns, equalTo(2)) assertThat(res.currentPageNumber, equalTo(1)) } diff --git a/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/conviction/Conviction.kt b/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/conviction/Conviction.kt index ad7e7519a7..4c780c4e33 100644 --- a/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/conviction/Conviction.kt +++ b/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/conviction/Conviction.kt @@ -151,6 +151,10 @@ data class Court( val courtType: KeyValue ) +data class CourtAppearanceBasicWrapper( + val courtAppearances: List = emptyList() +) + data class CourtAppearanceBasic( val courtAppearanceId: Long, val appearanceDate: LocalDateTime, diff --git a/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/proxy/CommunityApiController.kt b/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/proxy/CommunityApiController.kt index e1c6c2a26f..2f28b169d7 100644 --- a/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/proxy/CommunityApiController.kt +++ b/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/proxy/CommunityApiController.kt @@ -203,7 +203,7 @@ class CommunityApiController( mapOf( "crn" to crn, "convictionId" to convictionId - ), Uri.CONVICTION_BY_ID_NSIS, request + ), Uri.CONVICTION_BY_ID_PSS, request ) if (featureFlags.enabled("ccd-conviction-pss-enabled")) { @@ -212,6 +212,26 @@ class CommunityApiController( return proxy(request) } + @GetMapping("/offenders/crn/{crn}/convictions/{convictionId}/courtAppearances") + fun convictionByIdCourtAppearances( + request: HttpServletRequest, + @PathVariable crn: String, + @PathVariable convictionId: Long, + ): Any { + + sendComparisonReport( + mapOf( + "crn" to crn, + "convictionId" to convictionId + ), Uri.CONVICTION_BY_ID_COURT_APPEARANCES, request + ) + + if (featureFlags.enabled("ccd-conviction-by-id-court-appearances")) { + return convictionResource.getConvictionCourtAppearances(crn, convictionId) + } + return proxy(request) + } + @GetMapping("/**") fun proxy(request: HttpServletRequest): ResponseEntity { val headers = request.headerNames.asSequence().associateWith { request.getHeader(it) }.toMutableMap() diff --git a/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/proxy/Uri.kt b/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/proxy/Uri.kt index 2a666f8231..7bad3ae6bf 100644 --- a/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/proxy/Uri.kt +++ b/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/proxy/Uri.kt @@ -61,6 +61,11 @@ enum class Uri( "getPssRequirementsByConvictionId", listOf("crn", "convictionId"), ), - + CONVICTION_BY_ID_COURT_APPEARANCES( + "/secure/offenders/crn/{crn}/convictions/{convictionId}/courtAppearances", + "convictionResource", + "getConvictionCourtAppearances", + listOf("crn", "convictionId"), + ), DUMMY("/dummy", "dummyResource", "getDummy", listOf("crn")), } \ No newline at end of file diff --git a/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/resource/ConvictionResource.kt b/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/resource/ConvictionResource.kt index 7cff421e2e..388a1014ba 100644 --- a/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/resource/ConvictionResource.kt +++ b/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/resource/ConvictionResource.kt @@ -4,10 +4,7 @@ import io.swagger.v3.oas.annotations.Parameter import jakarta.validation.constraints.NotEmpty import org.springframework.security.access.prepost.PreAuthorize import org.springframework.web.bind.annotation.* -import uk.gov.justice.digital.hmpps.integrations.delius.service.AttendanceService -import uk.gov.justice.digital.hmpps.integrations.delius.service.ConvictionService -import uk.gov.justice.digital.hmpps.integrations.delius.service.InterventionService -import uk.gov.justice.digital.hmpps.integrations.delius.service.RequirementService +import uk.gov.justice.digital.hmpps.integrations.delius.service.* @RestController @RequestMapping("probation-case/{crn}/convictions") @@ -16,7 +13,8 @@ class ConvictionResource( private val convictionService: ConvictionService, private val requirementService: RequirementService, private val interventionService: InterventionService, - private val attendanceService: AttendanceService + private val attendanceService: AttendanceService, + private val courtAppearanceService: CourtAppearanceService ) { @GetMapping @@ -90,4 +88,10 @@ class ConvictionResource( @PathVariable crn: String, @PathVariable convictionId: Long ) = attendanceService.getAttendancesFor(crn, convictionId) + + @GetMapping("/{convictionId}/courtAppearances") + fun getConvictionCourtAppearances( + @PathVariable crn: String, + @PathVariable convictionId: Long + ) = courtAppearanceService.getCourtAppearancesFor(crn, convictionId) } diff --git a/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/event/courtappearance/entity/CourtAppearance.kt b/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/event/courtappearance/entity/CourtAppearance.kt index cfca18fd8d..1edc656b49 100644 --- a/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/event/courtappearance/entity/CourtAppearance.kt +++ b/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/event/courtappearance/entity/CourtAppearance.kt @@ -52,6 +52,11 @@ class CourtAppearance( } } +interface CourtAppearanceRepository : JpaRepository { + + fun findByPersonIdAndEventId(personId: Long, eventId: Long): List +} + interface CourtReportRepository : JpaRepository { @Query( diff --git a/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/service/CourtAppearanceService.kt b/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/service/CourtAppearanceService.kt new file mode 100644 index 0000000000..fd3d87903b --- /dev/null +++ b/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/service/CourtAppearanceService.kt @@ -0,0 +1,38 @@ +package uk.gov.justice.digital.hmpps.integrations.delius.service + +import org.springframework.stereotype.Service +import uk.gov.justice.digital.hmpps.api.model.KeyValue +import uk.gov.justice.digital.hmpps.api.model.conviction.CourtAppearanceBasic +import uk.gov.justice.digital.hmpps.api.model.conviction.CourtAppearanceBasicWrapper +import uk.gov.justice.digital.hmpps.integrations.delius.event.courtappearance.entity.CourtAppearance +import uk.gov.justice.digital.hmpps.integrations.delius.event.courtappearance.entity.CourtAppearanceRepository +import uk.gov.justice.digital.hmpps.integrations.delius.event.entity.EventRepository +import uk.gov.justice.digital.hmpps.integrations.delius.event.entity.getByPersonAndEventNumber +import uk.gov.justice.digital.hmpps.integrations.delius.person.entity.PersonRepository +import uk.gov.justice.digital.hmpps.integrations.delius.person.entity.getPerson + +@Service +class CourtAppearanceService( + private val personRepository: PersonRepository, + private val eventRepository: EventRepository, + private val courtAppearanceRepository: CourtAppearanceRepository +) { + + fun getCourtAppearancesFor(crn: String, eventId: Long): CourtAppearanceBasicWrapper { + val person = personRepository.getPerson(crn) + val event = eventRepository.getByPersonAndEventNumber(person, eventId) + val courtAppearances = courtAppearanceRepository.findByPersonIdAndEventId(person.id, event.id) + .sortedByDescending { it.appearanceDate } + .map { it.toCourtAppearance() } + return CourtAppearanceBasicWrapper(courtAppearances) + } +} + +fun CourtAppearance.toCourtAppearance() = CourtAppearanceBasic( + courtAppearanceId = id, + appearanceDate = appearanceDate.toLocalDateTime(), + courtCode = court.code, + courtName = court.courtName, + appearanceType = KeyValue(court.courtType.code, court.courtType.description), + crn = person.crn +)