Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MAN-113: Return MAPPA and OPD in risks #4498

Merged
merged 5 commits into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import org.springframework.transaction.annotation.Transactional
import uk.gov.justice.digital.hmpps.audit.BusinessInteraction
import uk.gov.justice.digital.hmpps.data.generator.*
import uk.gov.justice.digital.hmpps.data.generator.CourtAppearanceGenerator.COURT_APPEARANCE
import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator.GENDER_MALE
import uk.gov.justice.digital.hmpps.data.generator.personalDetails.PersonDetailsGenerator
import uk.gov.justice.digital.hmpps.integrations.delius.audit.BusinessInteractionCode
import uk.gov.justice.digital.hmpps.user.AuditUserRepository
Expand Down Expand Up @@ -53,7 +52,12 @@ class DataLoader(

entityManager.persist(ContactGenerator.LIMITED_ACCESS_USER)

entityManager.persist(GENDER_MALE)
entityManager.persistAll(
PersonGenerator.GENDER_MALE,
PersonGenerator.MAPPA_TYPE,
PersonGenerator.MAPPA_CATEGORY,
PersonGenerator.MAPPA_LEVEL
)

PersonGenerator.DISABILITIES.forEach { entityManager.persist(it.type) }
PersonGenerator.PROVISIONS.forEach { entityManager.persist(it.type) }
Expand Down Expand Up @@ -158,20 +162,24 @@ class DataLoader(
PersonGenerator.REQUIREMENT_CONTACT_2,
PersonGenerator.REGISTER_TYPE_1,
PersonGenerator.REGISTER_TYPE_2,
PersonGenerator.MAPPA_TYPE,
PersonGenerator.REGISTRATION_1,
PersonGenerator.REGISTRATION_2,
PersonGenerator.REGISTRATION_3,
PersonGenerator.MAPPA_REGISTRATION,
PersonGenerator.REGISTRATION_REVIEW_1,
PersonGenerator.REGISTRATION_REVIEW_2,
PersonGenerator.REGISTRATION_REVIEW_3,
PersonGenerator.DEREGISTRATION_1,
PersonGenerator.MAIN_CAT_F_TYPE,
PersonGenerator.MAIN_CAT_W_TYPE,
PersonGenerator.NSI_BREACH_TYPE,
PersonGenerator.NSI_OPD_TYPE,
PersonGenerator.NSI_STATUS,
PersonGenerator.BREACH_PREVIOUS_ORDER_1,
PersonGenerator.BREACH_PREVIOUS_ORDER_2,
PersonGenerator.BREACH_ON_ACTIVE_ORDER,
PersonGenerator.OPD_NSI,
UnpaidWorkApptGenerator.UNPAID_WORK_DETAILS_1,
UnpaidWorkApptGenerator.APPT1,
UnpaidWorkApptGenerator.APPT2,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,13 @@ import java.time.LocalDate
import java.time.LocalDateTime
import java.time.ZoneId
import java.time.ZonedDateTime
import java.time.temporal.ChronoUnit

object PersonGenerator {

val GENDER_MALE = ReferenceData(IdGenerator.getAndIncrement(), "M", "Male")
val MAPPA_CATEGORY = ReferenceData(IdGenerator.getAndIncrement(), "X9", "X9 Desc")
val MAPPA_LEVEL = ReferenceData(IdGenerator.getAndIncrement(), "M2", "M2 Desc")
val OVERVIEW = generateOverview("X000004")
val EVENT_1 = generateEvent(
OVERVIEW,
Expand Down Expand Up @@ -156,9 +159,12 @@ object PersonGenerator {

val REGISTER_TYPE_1 = generateRegisterType("CODE1", "Restraining Order")
val REGISTER_TYPE_2 = generateRegisterType("CODE2", "Domestic Abuse Perpetrator")
val REGISTRATION_1 = generateRegistration(REGISTER_TYPE_1, OVERVIEW.id, "Notes")
val REGISTRATION_2 = generateRegistration(REGISTER_TYPE_2, OVERVIEW.id, "Notes")
val REGISTRATION_3 = generateRegistration(REGISTER_TYPE_2, OVERVIEW.id, "Notes", deRegistered = true)
val MAPPA_TYPE = generateRegisterType("MAPP", "Mappa")
val REGISTRATION_1 = generateRegistration(REGISTER_TYPE_1, null, OVERVIEW.id, "Notes")
val REGISTRATION_2 = generateRegistration(REGISTER_TYPE_2, null, OVERVIEW.id, "Notes")
val REGISTRATION_3 = generateRegistration(REGISTER_TYPE_2, null, OVERVIEW.id, "Notes", deRegistered = true)

val MAPPA_REGISTRATION = generateRegistration(MAPPA_TYPE, MAPPA_CATEGORY, OVERVIEW.id, "Notes", level = MAPPA_LEVEL)

val REGISTRATION_REVIEW_1 = generateRiskReview(
REGISTRATION_2, LocalDate.now().minusDays(4),
Expand Down Expand Up @@ -460,20 +466,26 @@ object PersonGenerator {

fun generateRegistration(
type: RegisterType,
category: ReferenceData? = null,
personId: Long,
notes: String?,
id: Long = IdGenerator.getAndIncrement(),
deRegistered: Boolean = false
deRegistered: Boolean = false,
date: LocalDate = LocalDate.now(),
level: ReferenceData? = null,
) = RiskFlag(
personId,
type,
category,
deRegistered,
notes,
LocalDate.now(),
emptyList(),
USER,
LocalDate.now().plusDays(1),
emptyList(),
date,
level,
false,
id
)
Expand All @@ -495,11 +507,14 @@ object PersonGenerator {
) = RegistrationReview(riskFlag, date, reviewDue, notes, true, false, createdDate, IdGenerator.getAndIncrement())

val NSI_BREACH_TYPE = generateNsiType("BRE")
val NSI_OPD_TYPE = generateNsiType("OPD1")
val NSI_STATUS = generateNsiStatus("STATUS1", "An NSI Status")
val BREACH_PREVIOUS_ORDER_1 = generateNsi(OVERVIEW.id, INACTIVE_ORDER_1.event.id, NSI_BREACH_TYPE, NSI_STATUS)
val BREACH_PREVIOUS_ORDER_2 = generateNsi(OVERVIEW.id, INACTIVE_ORDER_2.event.id, NSI_BREACH_TYPE, NSI_STATUS)
val BREACH_ON_ACTIVE_ORDER = generateNsi(OVERVIEW.id, ACTIVE_ORDER.event.id, NSI_BREACH_TYPE, NSI_STATUS)

val OPD_NSI = generateNsi(OVERVIEW.id, ACTIVE_ORDER.event.id, NSI_OPD_TYPE, NSI_STATUS)

fun generateNsiType(code: String) = NsiType(id = IdGenerator.getAndIncrement(), code = code)
fun generateNsiStatus(code: String, description: String) =
NsiStatus(id = IdGenerator.getAndIncrement(), code = code, description = description)
Expand All @@ -508,7 +523,8 @@ object PersonGenerator {
personId: Long,
eventId: Long,
type: NsiType,
status: NsiStatus
status: NsiStatus,
active: Boolean = true

) = Nsi(
id = IdGenerator.getAndIncrement(),
Expand All @@ -517,7 +533,9 @@ object PersonGenerator {
expectedStartDate = LocalDate.now().minusDays(5),
eventId = eventId,
type = type,
nsiStatus = status
nsiStatus = status,
lastUpdated = ZonedDateTime.now().truncatedTo(ChronoUnit.SECONDS),
active = active
)

fun generateCaseload(caseLoadPerson: CaseloadPerson, staff: Staff, team: Team) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ internal class OverviewIntegrationTest {
assertThat(res.sentences[1].eventNumber, equalTo(EVENT_1.eventNumber))
assertThat(res.personalDetails.dateOfBirth, equalTo(OVERVIEW.dateOfBirth))
assertThat(res.personalDetails.dateOfBirth, equalTo(OVERVIEW.dateOfBirth))
assertThat(res.registrations, equalTo(listOf("Restraining Order", "Domestic Abuse Perpetrator")))
assertThat(res.registrations, equalTo(listOf("Restraining Order", "Domestic Abuse Perpetrator", "Mappa")))
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import uk.gov.justice.digital.hmpps.api.model.risk.PersonRiskFlag
import uk.gov.justice.digital.hmpps.api.model.risk.PersonRiskFlags
import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator.DEREGISTRATION_1
import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator.OVERVIEW
import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator.PERSON_2
import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator.REGISTRATION_2
import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator.REGISTRATION_3
import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator.REGISTRATION_REVIEW_2
Expand All @@ -37,7 +38,10 @@ internal class RiskFlagIntegrationTest {
.andExpect(status().isOk)
.andReturn().response.contentAsJson<PersonRiskFlags>()
assertThat(res.personSummary.crn, equalTo(person.crn))
assertThat(res.riskFlags.size, equalTo(2))
assertThat(res.mappa?.level, equalTo(2))
assertThat(res.mappa?.category, equalTo(0))
assertThat(res.opd?.eligible, equalTo(true))
assertThat(res.riskFlags.size, equalTo(3))
assertThat(res.riskFlags[1].description, equalTo(REGISTRATION_2.type.description))
assertThat(res.riskFlags[1].mostRecentReviewDate, equalTo(REGISTRATION_REVIEW_2.date))
assertThat(res.removedRiskFlags.size, equalTo(1))
Expand All @@ -52,6 +56,18 @@ internal class RiskFlagIntegrationTest {
)
}

@Test
fun `opd and mappa is not returned`() {
val person = PERSON_2
val res = mockMvc
.perform(get("/risk-flags/${person.crn}").withToken())
.andExpect(status().isOk)
.andReturn().response.contentAsJson<PersonRiskFlags>()
assertThat(res.personSummary.crn, equalTo(person.crn))
assertThat(res.mappa, equalTo(null))
assertThat(res.opd, equalTo(null))
}

@Test
fun `individual risk flag is returned`() {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package uk.gov.justice.digital.hmpps.api.model.risk

import java.time.LocalDate

data class MappaDetail(
val level: Int? = null,
val levelDescription: String? = null,
val category: Int? = null,
val categoryDescription: String? = null,
val startDate: LocalDate,
val reviewDate: LocalDate? = null,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package uk.gov.justice.digital.hmpps.api.model.risk

import java.time.ZonedDateTime

data class Opd(
val eligible: Boolean,
val date: ZonedDateTime,
)
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import uk.gov.justice.digital.hmpps.api.model.PersonSummary

data class PersonRiskFlags(
val personSummary: PersonSummary,
val opd: Opd? = null,
val mappa: MappaDetail? = null,
val riskFlags: List<RiskFlag>,
val removedRiskFlags: List<RiskFlag> = emptyList(),
)
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import org.hibernate.annotations.Immutable
import org.hibernate.annotations.SQLRestriction
import org.springframework.data.jpa.repository.JpaRepository
import java.time.LocalDate
import java.time.ZonedDateTime

@Immutable
@Entity
Expand Down Expand Up @@ -36,6 +37,9 @@ class Nsi(
@Column(name = "nsi_id")
val id: Long = 0,

@Column(name = "last_updated_datetime")
val lastUpdated: ZonedDateTime,

@Column(name = "active_flag", columnDefinition = "number")
val active: Boolean = true,

Expand Down Expand Up @@ -63,7 +67,17 @@ class NsiStatus(
@Immutable
@Entity
@Table(name = "r_nsi_type")
class NsiType(val code: String, @Id @Column(name = "nsi_type_id") val id: Long)
class NsiType(

val code: String,

@Id
@Column(name = "nsi_type_id") val id: Long
) {
enum class Code(val value: String) {
OPD_COMMUNITY_PATHWAY("OPD1")
}
}

interface NsiRepository : JpaRepository<Nsi, Long> {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,13 @@ import org.hibernate.annotations.FetchMode
import org.hibernate.annotations.Immutable
import org.hibernate.annotations.SQLRestriction
import org.hibernate.type.YesNoConverter
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.data.jpa.repository.Query
import uk.gov.justice.digital.hmpps.exception.NotFoundException
import uk.gov.justice.digital.hmpps.integrations.delius.overview.entity.RegisterType
import uk.gov.justice.digital.hmpps.integrations.delius.referencedata.entity.ReferenceData
import uk.gov.justice.digital.hmpps.integrations.delius.user.entity.Staff
import uk.gov.justice.digital.hmpps.integrations.delius.user.entity.User
import java.time.LocalDate
Expand All @@ -28,6 +32,10 @@ class RiskFlag(
@JoinColumn(name = "register_type_id")
val type: RegisterType,

@ManyToOne
@JoinColumn(name = "register_category_id")
val category: ReferenceData?,

@Column(name = "deregistered", columnDefinition = "number")
val deRegistered: Boolean,

Expand All @@ -51,6 +59,13 @@ class RiskFlag(
@OneToMany(mappedBy = "registration")
val reviews: List<RegistrationReview> = emptyList(),

@Column(name = "registration_date")
val date: LocalDate,

@ManyToOne
@JoinColumn(name = "register_level_id")
val level: ReferenceData?,

@Column(name = "soft_deleted", columnDefinition = "number")
val softDeleted: Boolean,

Expand All @@ -62,6 +77,18 @@ class RiskFlag(
interface RiskFlagRepository : JpaRepository<RiskFlag, Long> {
fun findByPersonId(personId: Long): List<RiskFlag>
fun findByPersonIdAndId(personId: Long, id: Long): RiskFlag?

@Query(
"""
select r from RiskFlag r
where r.type.code = 'MAPP'
and r.personId = :offenderId
and r.softDeleted = false
and r.deRegistered = false
order by r.date desc
"""
)
fun findActiveMappaRegistrationByOffenderId(offenderId: Long, pageable: Pageable): Page<RiskFlag>
}

fun RiskFlagRepository.getRiskFlag(personId: Long, id: Long): RiskFlag =
Expand Down
Loading
Loading