diff --git a/projects/court-case-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt b/projects/court-case-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt index 23902a317e..d3cf454de5 100644 --- a/projects/court-case-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt +++ b/projects/court-case-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt @@ -163,7 +163,8 @@ class DataLoader( val activePssRequirement = SentenceGenerator.generatePssRequirement(custody.id, active = true) val inactivePssRequirement = SentenceGenerator.generatePssRequirement(custody.id, active = false) val currentCourtAppearance = SentenceGenerator.COURT_APPEARANCE - val currentCourtReport = SentenceGenerator.generateCourtReport(currentCourtAppearance) + val currentCourtReport = + SentenceGenerator.generateCourtReport(currentCourtAppearance, PersonGenerator.CURRENTLY_MANAGED.id) val reportManager = SentenceGenerator.generateCourtReportManager(currentCourtReport) em.saveAll( diff --git a/projects/court-case-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/SentenceGenerator.kt b/projects/court-case-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/SentenceGenerator.kt index 882114c55b..73061633b1 100644 --- a/projects/court-case-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/SentenceGenerator.kt +++ b/projects/court-case-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/SentenceGenerator.kt @@ -371,11 +371,19 @@ object SentenceGenerator { id = id ) - fun generateCourtReport(courtAppearance: CourtAppearance, id: Long = IdGenerator.getAndIncrement()) = + fun generateCourtReport( + courtAppearance: CourtAppearance, + personId: Long, + id: Long = IdGenerator.getAndIncrement() + ) = CourtReport( - LocalDate.now(), - LocalDate.now().plusDays(5), + personId, + LocalDateTime.now().truncatedTo(ChronoUnit.MICROS), + LocalDateTime.now().plusDays(5).truncatedTo(ChronoUnit.MICROS), null, + LocalDateTime.now().truncatedTo(ChronoUnit.MICROS), + LocalDateTime.now().truncatedTo(ChronoUnit.MICROS), + LocalDateTime.now().truncatedTo(ChronoUnit.MICROS), ReferenceDataGenerator.COURT_REPORT_TYPE, null, courtAppearance, diff --git a/projects/court-case-and-delius/src/dev/resources/simulations/__files/get_court_reports_C123456.json b/projects/court-case-and-delius/src/dev/resources/simulations/__files/get_court_reports_C123456.json new file mode 100644 index 0000000000..d11b9bc24f --- /dev/null +++ b/projects/court-case-and-delius/src/dev/resources/simulations/__files/get_court_reports_C123456.json @@ -0,0 +1,25 @@ +[ + { + "courtReportId": 125, + "offenderId": 65, + "requestedDate": "2024-08-06T18:59:19.420309", + "requiredDate": "2024-08-11T18:59:19.420318", + "allocationDate": "2024-08-06T18:59:19.420326", + "sentToCourtDate": "2024-08-06T18:59:19.420329", + "receivedByCourtDate": "2024-08-06T18:59:19.420332", + "courtReportType": { + "code": "CR1", + "description": "court report" + }, + "reportManagers": [ + { + "staff": { + "code": "N01ABBA", + "forenames": "Bob Micheal", + "surname": "Smith" + }, + "active": true + } + ] + } +] \ 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 1c93da50f5..aa91910dab 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}/courtReports" + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/json" + }, + "bodyFileName": "get_court_reports_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 4a23dbc796..98b05b05e2 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 @@ -285,4 +285,18 @@ internal class ConvictionByCrnAndEventIdIntegrationTest { assertThat(response.courtAppearances[0], equalTo(COURT_APPEARANCE.toCourtAppearance())) } + + @Test + fun `call convictions by id and courtReports`() { + val crn = PersonGenerator.CURRENTLY_MANAGED.crn + val event = SentenceGenerator.CURRENTLY_MANAGED + + val response = mockMvc + .perform(get("/probation-case/$crn/convictions/${event.id}/courtReports").withToken()) + .andExpect(status().isOk) + .andReturn().response.contentAsJson>() + + assertThat(response.size, equalTo(1)) + assertThat(response[0].reportManagers?.size, equalTo(1)) + } } \ 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 46c82890b2..2366a8a560 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 @@ -249,6 +249,10 @@ internal class ProxyIntegrationTest { "CONVICTION_BY_ID_COURT_APPEARANCES": { "convictionId": "?", "activeOnly": true + }, + "CONVICTION_BY_ID_COURT_REPORTS": { + "convictionId": "?", + "activeOnly": true } } } @@ -257,7 +261,7 @@ internal class ProxyIntegrationTest { .withToken() ).andExpect(status().is2xxSuccessful).andReturn().response.contentAsJson() - assertThat(res.totalNumberOfRequests, equalTo(11)) + assertThat(res.totalNumberOfRequests, equalTo(12)) 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/Offender.kt b/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/Offender.kt index 36718f9de8..3d3216b600 100644 --- a/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/Offender.kt +++ b/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/Offender.kt @@ -82,7 +82,7 @@ data class StaffHuman( val code: String, val forenames: String, val surname: String, - val unallocated: Boolean + val unallocated: Boolean? = null ) data class Institution( diff --git a/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/conviction/CourtReports.kt b/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/conviction/CourtReports.kt new file mode 100644 index 0000000000..372f01adce --- /dev/null +++ b/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/conviction/CourtReports.kt @@ -0,0 +1,25 @@ +package uk.gov.justice.digital.hmpps.api.model.conviction + +import uk.gov.justice.digital.hmpps.api.model.KeyValue +import uk.gov.justice.digital.hmpps.api.model.StaffHuman +import java.time.LocalDateTime + +data class CourtReportMinimal( + val courtReportId: Long, + val offenderId: Long, + val requestedDate: LocalDateTime, + val requiredDate: LocalDateTime, + val allocationDate: LocalDateTime? = null, + val completedDate: LocalDateTime? = null, + val sentToCourtDate: LocalDateTime? = null, + val receivedByCourtDate: LocalDateTime? = null, + val courtReportType: KeyValue? = null, + val reportManagers: List = emptyList(), + val deliveredCourtReportType: KeyValue? = null, + +) + +data class ReportManager( + val staff: StaffHuman?, + val active: Boolean +) \ No newline at end of file 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 2f28b169d7..5928bd303b 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 @@ -232,6 +232,26 @@ class CommunityApiController( return proxy(request) } + @GetMapping("/offenders/crn/{crn}/convictions/{convictionId}/courtReports") + fun convictionByIdCourtReports( + request: HttpServletRequest, + @PathVariable crn: String, + @PathVariable convictionId: Long, + ): Any { + + sendComparisonReport( + mapOf( + "crn" to crn, + "convictionId" to convictionId + ), Uri.CONVICTION_BY_ID_COURT_REPORTS, request + ) + + if (featureFlags.enabled("ccd-conviction-by-id-court-reports")) { + return convictionResource.getConvictionCourtReports(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 7bad3ae6bf..b584f12599 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 @@ -67,5 +67,11 @@ enum class Uri( "getConvictionCourtAppearances", listOf("crn", "convictionId"), ), + CONVICTION_BY_ID_COURT_REPORTS( + "/secure/offenders/crn/{crn}/convictions/{convictionId}/courtReports", + "convictionResource", + "getConvictionCourtReports", + 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 388a1014ba..7941b5eae2 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 @@ -14,7 +14,8 @@ class ConvictionResource( private val requirementService: RequirementService, private val interventionService: InterventionService, private val attendanceService: AttendanceService, - private val courtAppearanceService: CourtAppearanceService + private val courtAppearanceService: CourtAppearanceService, + private val courtReportService: CourtReportService ) { @GetMapping @@ -94,4 +95,10 @@ class ConvictionResource( @PathVariable crn: String, @PathVariable convictionId: Long ) = courtAppearanceService.getCourtAppearancesFor(crn, convictionId) + + @GetMapping("/{convictionId}/courtReports") + fun getConvictionCourtReports( + @PathVariable crn: String, + @PathVariable convictionId: Long + ) = courtReportService.getCourtReportsFor(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 d81296dcd8..ddd734e03f 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 @@ -10,7 +10,6 @@ import uk.gov.justice.digital.hmpps.integrations.delius.event.entity.Event import uk.gov.justice.digital.hmpps.integrations.delius.event.sentence.entity.Court import uk.gov.justice.digital.hmpps.integrations.delius.person.entity.Person import uk.gov.justice.digital.hmpps.integrations.delius.provider.entity.Staff -import java.time.LocalDate import java.time.LocalDateTime @Entity @@ -18,6 +17,7 @@ import java.time.LocalDateTime @Table(name = "court_appearance") @SQLRestriction("soft_deleted = 0") class CourtAppearance( + @JoinColumn(name = "event_id") @ManyToOne val event: Event, @@ -66,6 +66,17 @@ interface CourtReportRepository : JpaRepository { """ ) fun getAllByEvent(event: Event): List + + @Query( + """ + select courtReport + from CourtReport courtReport + where courtReport.personId = :personId + and courtReport.courtAppearance.event.id = :eventId + and courtReport.softDeleted = false + """ + ) + fun findByPersonIdAndEventId(personId: Long, eventId: Long): List } @Immutable @@ -92,12 +103,24 @@ class Outcome( @Table(name = "court_report") @SQLRestriction("soft_deleted = 0") class CourtReport( + + @Column(name = "offender_id") + val personId: Long, @Column(name = "date_requested") - val dateRequested: LocalDate, + val dateRequested: LocalDateTime, @Column(name = "date_required") - val dateRequired: LocalDate, + val dateRequired: LocalDateTime, @Column(name = "completed_Date") - val dateCompleted: LocalDate?, + val dateCompleted: LocalDateTime?, + + @Column(name = "allocation_date") + val allocationDate: LocalDateTime? = null, + + @Column(name = "sent_to_court_date") + val sentToCourtDate: LocalDateTime? = null, + + @Column(name = "received_by_court_date") + val receivedByCourtDate: LocalDateTime? = null, @ManyToOne @JoinColumn(name = "court_report_type_id") @@ -133,7 +156,7 @@ class ReportManager( @JoinColumn(name = "staff_id") @OneToOne - val staff: Staff, + val staff: Staff? = null, @Column(name = "active_flag", columnDefinition = "number") var active: Boolean, diff --git a/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/service/CourtReportService.kt b/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/service/CourtReportService.kt new file mode 100644 index 0000000000..9516c4b0d5 --- /dev/null +++ b/projects/court-case-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/service/CourtReportService.kt @@ -0,0 +1,54 @@ +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.StaffHuman +import uk.gov.justice.digital.hmpps.api.model.conviction.CourtReportMinimal +import uk.gov.justice.digital.hmpps.integrations.delius.event.courtappearance.entity.CourtReport +import uk.gov.justice.digital.hmpps.integrations.delius.event.courtappearance.entity.CourtReportRepository +import uk.gov.justice.digital.hmpps.integrations.delius.event.courtappearance.entity.ReportManager +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 +import uk.gov.justice.digital.hmpps.integrations.delius.provider.entity.Staff + +@Service +class CourtReportService( + private val personRepository: PersonRepository, + private val eventRepository: EventRepository, + private val courtReportRepository: CourtReportRepository +) { + + fun getCourtReportsFor(crn: String, eventId: Long): List { + val person = personRepository.getPerson(crn) + val event = eventRepository.getByPersonAndEventNumber(person, eventId) + return courtReportRepository.findByPersonIdAndEventId(person.id, event.id) + .map { it.toCourtReport() } + } +} + +fun CourtReport.toCourtReport() = CourtReportMinimal( + courtReportId = id, + offenderId = personId, + requestedDate = dateRequested, + requiredDate = dateRequired, + allocationDate = allocationDate, + completedDate = dateCompleted, + sentToCourtDate = sentToCourtDate, + receivedByCourtDate = receivedByCourtDate, + courtReportType = courtReportType?.let { KeyValue(it.code, it.description) }, + reportManagers = reportManagers.filter { it.staff != null }.map { it.toReportManager() }, + deliveredCourtReportType = deliveredCourtReportType?.let { KeyValue(it.code, it.description) } +) + +fun Staff.toStaffHuman() = StaffHuman( + forenames = listOfNotNull(forename, forename2).joinToString(" "), + surname = surname, + code = code +) + +fun ReportManager.toReportManager() = uk.gov.justice.digital.hmpps.api.model.conviction.ReportManager( + active = active, + staff = staff?.toStaffHuman() +)