Skip to content

Commit

Permalink
Feature/pi 1939 mas overview tab delius integration api offence tab (#…
Browse files Browse the repository at this point in the history
…3454)

* PI-1939 - add new api to return most recent active event

* PI-1939 - small refactor with clear ide warning messages

* PI-1939 - refactor offence count to Long

* PI-1939 - refactor entity names

* PI-1939 - update service test

* PI-1939 - add controller and integration test

* PI-1939 - refactor integration layer and update integration test

* PI-1939 - update service test

* Formatting changes

* PI-1939 - refactor code and apply review comments

* PI-1939 - update tests

* PI-1939 - get all active sentences, instead of latest sentence

* Formatting changes

* PI-1939 - update sql to only query required tables

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
  • Loading branch information
achimber-moj and github-actions[bot] authored Mar 12, 2024
1 parent f7dca6a commit ba72fef
Show file tree
Hide file tree
Showing 11 changed files with 327 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,42 @@ import java.time.ZonedDateTime
object PersonGenerator {

val OVERVIEW = generateOverview("X000004")
val EVENT_1 = generateEvent(OVERVIEW, eventNumber = "7654321")
val EVENT_2 = generateEvent(OVERVIEW, eventNumber = "1234567", inBreach = true)
val INACTIVE_EVENT_1 = generateEvent(OVERVIEW, eventNumber = "654321", inBreach = true, active = false)
val INACTIVE_EVENT_2 = generateEvent(OVERVIEW, eventNumber = "854321", inBreach = true, active = false)
val EVENT_1 = generateEvent(OVERVIEW, eventNumber = "7654321", notes = "overview", additionalOffences = emptyList())
val EVENT_2 = generateEvent(
OVERVIEW,
eventNumber = "1234567",
inBreach = true,
notes = "overview",
additionalOffences = emptyList()
)
val INACTIVE_EVENT_1 = generateEvent(
OVERVIEW,
eventNumber = "654321",
inBreach = true,
active = false,
notes = "inactive",
additionalOffences = emptyList()
)
val INACTIVE_EVENT_2 = generateEvent(
OVERVIEW,
eventNumber = "854321",
inBreach = true,
active = false,
notes = "inactive",
additionalOffences = emptyList()
)
val OFFENCE_1 = generateOffence("Murder", "MAIN")
val OFFENCE_2 = generateOffence("Another Murder", "MAINA")

val MAIN_OFFENCE_1 = generateMainOffence(
1,
EVENT_1,
OFFENCE_1,
LocalDate.now()
)

val MAIN_OFFENCE_2 = generateMainOffence(
1,
EVENT_2,
OFFENCE_2,
LocalDate.now()
Expand All @@ -37,13 +59,15 @@ object PersonGenerator {

val ADD_OFF_1 = generateOffence("Burglary", "ADD1")
val ADDITIONAL_OFFENCE_1 = generateAdditionalOffence(
1,
EVENT_1,
ADD_OFF_1,
LocalDate.now()
)

val ADD_OFF_2 = generateOffence("Assault", "ADD2")
val ADDITIONAL_OFFENCE_2 = generateAdditionalOffence(
1,
EVENT_1,
ADD_OFF_2,
LocalDate.now()
Expand Down Expand Up @@ -82,7 +106,9 @@ object PersonGenerator {
active: Boolean = true,
inBreach: Boolean = false,
disposal: Disposal? = null,
mainOffence: MainOffence? = null
mainOffence: MainOffence? = null,
notes: String,
additionalOffences: List<AdditionalOffence>
) =
Event(
id,
Expand All @@ -91,7 +117,9 @@ object PersonGenerator {
disposal = disposal,
inBreach = inBreach,
active = active,
mainOffence = mainOffence
mainOffence = mainOffence,
notes = notes,
additionalOffences = additionalOffences
)

fun generateOverview(
Expand Down Expand Up @@ -208,20 +236,22 @@ object PersonGenerator {
) = Offence(id, code, description)

fun generateMainOffence(
offenceCount: Long,
event: Event,
offence: Offence,
date: LocalDate,
id: Long = IdGenerator.getAndIncrement(),
softDeleted: Boolean = false
) = MainOffence(id, event, date, offence, softDeleted)
) = MainOffence(id, offenceCount, event, date, offence, softDeleted)

fun generateAdditionalOffence(
offenceCount: Long,
event: Event,
offence: Offence,
date: LocalDate,
id: Long = IdGenerator.getAndIncrement(),
softDeleted: Boolean = false
) = AdditionalOffence(id, event, date, offence, softDeleted)
) = AdditionalOffence(id, offenceCount, event, date, offence, softDeleted)

fun generateRegisterType(
code: String,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package uk.gov.justice.digital.hmpps

import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders
import org.springframework.test.web.servlet.result.MockMvcResultMatchers
import uk.gov.justice.digital.hmpps.api.model.sentence.MainOffence
import uk.gov.justice.digital.hmpps.api.model.sentence.Offence
import uk.gov.justice.digital.hmpps.api.model.sentence.SentenceOverview
import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator
import uk.gov.justice.digital.hmpps.test.MockMvcExtensions.contentAsJson
import uk.gov.justice.digital.hmpps.test.MockMvcExtensions.withToken
import java.time.LocalDate

@AutoConfigureMockMvc
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class SentenceIntegrationTest {
@Autowired
lateinit var mockMvc: MockMvc

@Test
fun `get active sentences`() {
val response = mockMvc
.perform(MockMvcRequestBuilders.get("/sentence/${PersonGenerator.OVERVIEW.crn}").withToken())
.andExpect(MockMvcResultMatchers.status().isOk)
.andReturn().response.contentAsJson<SentenceOverview>()

val expected = SentenceOverview(
listOf(
MainOffence(
Offence("Murder", 1),
LocalDate.of(2024, 3, 12),
"overview",
listOf(
Offence("Burglary", 1),
Offence("Assault", 1)
)
),
MainOffence(
Offence("Another Murder", 1),
LocalDate.of(2024, 3, 12),
"overview",
emptyList()
)
)
)

assertEquals(expected, response)
}

@Test
fun `unauthorized status returned`() {
mockMvc
.perform(MockMvcRequestBuilders.get("/sentence/X123456"))
.andExpect(MockMvcResultMatchers.status().isUnauthorized)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package uk.gov.justice.digital.hmpps.api.controller

import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.tags.Tag
import org.springframework.security.access.prepost.PreAuthorize
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.digital.hmpps.service.SentenceService

@RestController
@Tag(name = "Sentence")
@RequestMapping("/sentence/{crn}")
@PreAuthorize("hasRole('PROBATION_API__MANAGE_A_SUPERVISION__CASE_DETAIL')")
class SentenceController(private val sentenceService: SentenceService) {

@GetMapping
@Operation(summary = "Display the most recent ‘Active Event’ ")
fun getOverview(@PathVariable crn: String) = sentenceService.getMostRecentActiveEvent(crn)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package uk.gov.justice.digital.hmpps.api.model.sentence

import java.time.LocalDate

data class MainOffence(
val offence: Offence,
val dateOfOffence: LocalDate,
val notes: String,
val additionalOffences: List<Offence>
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package uk.gov.justice.digital.hmpps.api.model.sentence

data class Offence(
val description: String,
val count: Long
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package uk.gov.justice.digital.hmpps.api.model.sentence

data class SentenceOverview(
val offence: List<MainOffence?>

)
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ class Event(
@OneToMany(mappedBy = "event")
val additionalOffences: List<AdditionalOffence> = emptyList(),

@Column(name = "notes")
val notes: String,

@Column(columnDefinition = "number")
val softDeleted: Boolean = false
)
Expand Down Expand Up @@ -121,6 +124,9 @@ class MainOffence(
@Column(name = "main_offence_id")
val id: Long,

@Column(name = "offence_count")
val offenceCount: Long,

@OneToOne
@JoinColumn(name = "event_id", nullable = false)
val event: Event,
Expand All @@ -145,6 +151,9 @@ class AdditionalOffence(
@Column(name = "additional_offence_id")
val id: Long,

@Column(name = "offence_count")
val offenceCount: Long,

@ManyToOne
@JoinColumn(name = "event_id", nullable = false)
val event: Event?,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package uk.gov.justice.digital.hmpps.integrations.delius.sentence.entity

import jakarta.persistence.Column
import jakarta.persistence.Entity
import jakarta.persistence.Id
import jakarta.persistence.Table
import org.hibernate.annotations.Immutable
import org.hibernate.annotations.SQLRestriction
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.data.jpa.repository.Query
import uk.gov.justice.digital.hmpps.integrations.delius.overview.entity.Event

interface EventSentenceRepository : JpaRepository<Event, Long> {

@Immutable
@Entity
@Table(name = "offender")
@SQLRestriction("soft_deleted = 0")
class Person(
@Id
@Column(name = "offender_id")
val id: Long,

@Column(columnDefinition = "char(7)")
val crn: String
)

@Query(
"SELECT e FROM Event e " +
"JOIN Person p ON p.id = e.personId " +
"LEFT JOIN FETCH e.mainOffence m " +
"LEFT JOIN FETCH e.additionalOffences ao " +
"LEFT JOIN FETCH m.offence mo " +
"LEFT JOIN FETCH ao.offence aoo " +
"WHERE p.crn = :crn " +
"AND e.active = true "
)
fun findActiveSentencesByCrn(crn: String): List<Event>
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package uk.gov.justice.digital.hmpps.service

import org.springframework.stereotype.Service
import uk.gov.justice.digital.hmpps.api.model.sentence.MainOffence
import uk.gov.justice.digital.hmpps.api.model.sentence.Offence
import uk.gov.justice.digital.hmpps.api.model.sentence.SentenceOverview
import uk.gov.justice.digital.hmpps.integrations.delius.overview.entity.Event
import uk.gov.justice.digital.hmpps.integrations.delius.sentence.entity.EventSentenceRepository

@Service
class SentenceService(
private val eventRepository: EventSentenceRepository
) {
fun getMostRecentActiveEvent(crn: String): SentenceOverview {
val events = eventRepository.findActiveSentencesByCrn(crn)

return SentenceOverview(events.map { it.toOffence() })
}

fun Event.toOffence() = mainOffence?.let { mainOffence ->
MainOffence(offence = Offence(
mainOffence.offence.description, mainOffence.offenceCount
),
dateOfOffence = mainOffence.date,
notes = notes,
additionalOffences = additionalOffences.map {
Offence(
description = it.offence.description, count = it.offenceCount
)
}
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,19 @@ internal class OverviewServiceTest {
inBreach = false,
disposal = PersonGenerator.ACTIVE_ORDER,
eventNumber = "654321",
mainOffence = PersonGenerator.MAIN_OFFENCE_1
mainOffence = PersonGenerator.MAIN_OFFENCE_1,
notes = "overview",
additionalOffences = emptyList()
),
generateEvent(
person = PersonGenerator.OVERVIEW,
active = true,
inBreach = false,
disposal = PersonGenerator.ACTIVE_ORDER,
eventNumber = "654321",
mainOffence = PersonGenerator.MAIN_OFFENCE_2
mainOffence = PersonGenerator.MAIN_OFFENCE_2,
notes = "overview",
additionalOffences = emptyList()
),
PersonGenerator.INACTIVE_EVENT_1,
PersonGenerator.INACTIVE_EVENT_2
Expand Down
Loading

0 comments on commit ba72fef

Please sign in to comment.