diff --git a/projects/approved-premises-and-delius/build.gradle.kts b/projects/approved-premises-and-delius/build.gradle.kts index 78d13d14f2..7881d33e52 100644 --- a/projects/approved-premises-and-delius/build.gradle.kts +++ b/projects/approved-premises-and-delius/build.gradle.kts @@ -5,6 +5,7 @@ apply(plugin = "com.google.cloud.tools.jib") dependencies { implementation(project(":libs:audit")) implementation(project(":libs:commons")) + implementation(project(":libs:limited-access")) implementation(project(":libs:messaging")) implementation(project(":libs:oauth-client")) implementation(project(":libs:oauth-server")) diff --git a/projects/approved-premises-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt b/projects/approved-premises-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt index 9623f7e431..f2fd6e6fd7 100644 --- a/projects/approved-premises-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt +++ b/projects/approved-premises-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt @@ -51,6 +51,7 @@ import uk.gov.justice.digital.hmpps.integrations.delius.referencedata.ReferenceD import uk.gov.justice.digital.hmpps.integrations.delius.staff.StaffRepository import uk.gov.justice.digital.hmpps.integrations.delius.team.TeamRepository import uk.gov.justice.digital.hmpps.user.AuditUserRepository +import java.time.LocalDate @Component @ConditionalOnProperty("seed.database") @@ -78,7 +79,8 @@ class DataLoader( private val transferReasonRepository: TransferReasonRepository, private val caseloadRepository: CaseloadRepository, private val registrationRepository: RegistrationRepository, - private val referralRepository: ReferralRepository + private val referralRepository: ReferralRepository, + private val probationCaseDataLoader: ProbationCaseDataLoader ) : ApplicationListener { @PostConstruct @@ -159,7 +161,8 @@ class DataLoader( registrationRepository.save( PersonGenerator.generateRegistration( person, - ReferenceDataGenerator.REGISTER_TYPES[RegisterType.Code.GANG_AFFILIATION.value]!! + ReferenceDataGenerator.REGISTER_TYPES[RegisterType.Code.GANG_AFFILIATION.value]!!, + LocalDate.now() ) ) @@ -179,6 +182,8 @@ class DataLoader( caseloadRepository.save(CaseloadGenerator.generate(person, TeamGenerator.UNALLOCATED)) referralRepository.save(ReferralGenerator.EXISTING_REFERRAL) + + probationCaseDataLoader.loadData() } } diff --git a/projects/approved-premises-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/ProbationCaseDataLoader.kt b/projects/approved-premises-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/ProbationCaseDataLoader.kt new file mode 100644 index 0000000000..863157272c --- /dev/null +++ b/projects/approved-premises-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/ProbationCaseDataLoader.kt @@ -0,0 +1,94 @@ +package uk.gov.justice.digital.hmpps.data + +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.stereotype.Component +import uk.gov.justice.digital.hmpps.data.generator.OffenceGenerator +import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator +import uk.gov.justice.digital.hmpps.data.generator.ProbationCaseGenerator +import uk.gov.justice.digital.hmpps.data.generator.ReferenceDataGenerator +import uk.gov.justice.digital.hmpps.data.generator.asPerson +import uk.gov.justice.digital.hmpps.data.generator.asPersonManager +import uk.gov.justice.digital.hmpps.data.generator.asTeam +import uk.gov.justice.digital.hmpps.integrations.delius.approvedpremises.referral.entity.EventRepository +import uk.gov.justice.digital.hmpps.integrations.delius.person.ProbationCaseRepository +import uk.gov.justice.digital.hmpps.integrations.delius.person.manager.probation.PersonManagerRepository +import uk.gov.justice.digital.hmpps.integrations.delius.person.offence.entity.AdditionalOffence +import uk.gov.justice.digital.hmpps.integrations.delius.person.offence.entity.MainOffenceRepository +import uk.gov.justice.digital.hmpps.integrations.delius.person.offence.entity.Offence +import uk.gov.justice.digital.hmpps.integrations.delius.person.registration.entity.RegisterType +import uk.gov.justice.digital.hmpps.integrations.delius.person.registration.entity.RegistrationRepository +import uk.gov.justice.digital.hmpps.integrations.delius.staff.StaffRepository +import uk.gov.justice.digital.hmpps.integrations.delius.team.TeamRepository +import java.time.LocalDate + +@Component +class ProbationCaseDataLoader( + private val probationAreaRepository: ProbationAreaRepository, + private val teamRepository: TeamRepository, + private val staffRepository: StaffRepository, + private val personManagerRepository: PersonManagerRepository, + private val probationCaseRepository: ProbationCaseRepository, + private val registrationRepository: RegistrationRepository, + private val eventRepository: EventRepository, + private val offenceRepository: OffenceRepository, + private val mainOffenceRepository: MainOffenceRepository, + private val additionalOffenceRepository: AdditionalOffenceRepository +) { + fun loadData() { + offenceRepository.saveAll(listOf(OffenceGenerator.OFFENCE_ONE, OffenceGenerator.OFFENCE_TWO)) + probationAreaRepository.save(ProbationCaseGenerator.COM_PROVIDER) + teamRepository.save(ProbationCaseGenerator.COM_TEAM.asTeam()) + staffRepository.save(ProbationCaseGenerator.COM_UNALLOCATED) + probationCaseRepository.save(ProbationCaseGenerator.CASE_COMPLEX) + probationCaseRepository.save(ProbationCaseGenerator.CASE_SIMPLE) + + personManagerRepository.saveAll( + listOf( + ProbationCaseGenerator.generateManager(ProbationCaseGenerator.CASE_COMPLEX).asPersonManager(), + ProbationCaseGenerator.generateManager(ProbationCaseGenerator.CASE_SIMPLE).asPersonManager() + ) + ) + + registrationRepository.save( + PersonGenerator.generateRegistration( + ProbationCaseGenerator.CASE_COMPLEX.asPerson(), + ReferenceDataGenerator.REGISTER_TYPES[RegisterType.Code.MAPPA.value]!!, + LocalDate.now().minusDays(7), + ReferenceDataGenerator.REGISTER_CATEGORIES["M3"], + ReferenceDataGenerator.REGISTER_LEVELS["M2"] + ) + ) + + registrationRepository.save( + PersonGenerator.generateRegistration( + ProbationCaseGenerator.CASE_COMPLEX.asPerson(), + ReferenceDataGenerator.REGISTER_TYPES[RegisterType.Code.SEX_OFFENCE.value]!!, + LocalDate.now().minusDays(7) + ) + ) + + val event = PersonGenerator.generateEvent( + "1", + ProbationCaseGenerator.CASE_COMPLEX.id + ).apply(eventRepository::save) + + mainOffenceRepository.save( + OffenceGenerator.generateMainOffence( + event, + OffenceGenerator.OFFENCE_ONE, + LocalDate.now().minusDays(7) + ) + ) + + additionalOffenceRepository.save( + OffenceGenerator.generateAdditionalOffence( + event, + OffenceGenerator.OFFENCE_TWO, + LocalDate.now().minusDays(5) + ) + ) + } +} + +interface OffenceRepository : JpaRepository +interface AdditionalOffenceRepository : JpaRepository diff --git a/projects/approved-premises-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/OffenceGenerator.kt b/projects/approved-premises-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/OffenceGenerator.kt new file mode 100644 index 0000000000..173f67158f --- /dev/null +++ b/projects/approved-premises-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/OffenceGenerator.kt @@ -0,0 +1,31 @@ +package uk.gov.justice.digital.hmpps.data.generator + +import uk.gov.justice.digital.hmpps.integrations.delius.approvedpremises.referral.entity.Event +import uk.gov.justice.digital.hmpps.integrations.delius.person.offence.entity.AdditionalOffence +import uk.gov.justice.digital.hmpps.integrations.delius.person.offence.entity.MainOffence +import uk.gov.justice.digital.hmpps.integrations.delius.person.offence.entity.Offence +import java.time.LocalDate + +object OffenceGenerator { + val OFFENCE_ONE = generate("OFF1", "Offence One") + val OFFENCE_TWO = generate("OFF2", "Offence Two") + + fun generate(code: String, description: String, id: Long = IdGenerator.getAndIncrement()) = + Offence(code, description, id) + + fun generateMainOffence( + event: Event, + offence: Offence, + date: LocalDate, + softDeleted: Boolean = false, + id: Long = IdGenerator.getAndIncrement() + ) = MainOffence(event, offence, date, softDeleted, id) + + fun generateAdditionalOffence( + event: Event, + offence: Offence, + date: LocalDate, + softDeleted: Boolean = false, + id: Long = IdGenerator.getAndIncrement() + ) = AdditionalOffence(event, offence, date, softDeleted, id) +} diff --git a/projects/approved-premises-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/PersonGenerator.kt b/projects/approved-premises-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/PersonGenerator.kt index dbf961c5e4..0da29c0517 100644 --- a/projects/approved-premises-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/PersonGenerator.kt +++ b/projects/approved-premises-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/PersonGenerator.kt @@ -5,27 +5,39 @@ import uk.gov.justice.digital.hmpps.integrations.delius.person.Person import uk.gov.justice.digital.hmpps.integrations.delius.person.manager.probation.PersonManager import uk.gov.justice.digital.hmpps.integrations.delius.person.registration.entity.RegisterType import uk.gov.justice.digital.hmpps.integrations.delius.person.registration.entity.Registration +import uk.gov.justice.digital.hmpps.integrations.delius.referencedata.ReferenceData import uk.gov.justice.digital.hmpps.integrations.delius.staff.Staff import uk.gov.justice.digital.hmpps.integrations.delius.team.Team +import java.time.LocalDate +import java.time.ZonedDateTime object PersonGenerator { val DEFAULT = generate(crn = "A000001") - val EVENT = PersonGenerator.generateEvent("7", DEFAULT.id) + val EVENT = generateEvent("7", DEFAULT.id) fun generate( crn: String, id: Long = IdGenerator.getAndIncrement() ) = Person(id = id, crn = crn) - fun generateEvent(number: String, personId: Long, id: Long = IdGenerator.getAndIncrement()) = - Event(id, number, personId) + fun generateEvent( + number: String, + personId: Long, + active: Boolean = true, + softDeleted: Boolean = false, + id: Long = IdGenerator.getAndIncrement() + ) = Event(id, number, personId, active, softDeleted) fun generateRegistration( person: Person, type: RegisterType, + date: LocalDate, + category: ReferenceData? = null, + level: ReferenceData? = null, softDeleted: Boolean = false, deregistered: Boolean = false, + lastUpdatedDateTime: ZonedDateTime = ZonedDateTime.now(), id: Long = IdGenerator.getAndIncrement() - ) = Registration(person.id, type, softDeleted, deregistered, id) + ) = Registration(person.id, type, category, level, date, softDeleted, deregistered, lastUpdatedDateTime, id) } object PersonManagerGenerator { diff --git a/projects/approved-premises-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/ProbationCaseGenerator.kt b/projects/approved-premises-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/ProbationCaseGenerator.kt new file mode 100644 index 0000000000..7c03b4a56c --- /dev/null +++ b/projects/approved-premises-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/ProbationCaseGenerator.kt @@ -0,0 +1,87 @@ +package uk.gov.justice.digital.hmpps.data.generator + +import uk.gov.justice.digital.hmpps.data.generator.ProbationCaseGenerator.COM_PROVIDER +import uk.gov.justice.digital.hmpps.data.generator.ProbationCaseGenerator.COM_TEAM +import uk.gov.justice.digital.hmpps.data.generator.ProbationCaseGenerator.COM_UNALLOCATED +import uk.gov.justice.digital.hmpps.integrations.delius.person.CommunityManager +import uk.gov.justice.digital.hmpps.integrations.delius.person.CommunityManagerTeam +import uk.gov.justice.digital.hmpps.integrations.delius.person.ProbationCase +import uk.gov.justice.digital.hmpps.integrations.delius.referencedata.ReferenceData +import uk.gov.justice.digital.hmpps.integrations.delius.team.Team +import java.time.LocalDate + +object ProbationCaseGenerator { + val COM_PROVIDER = ProbationAreaGenerator.generate("N01") + val COM_TEAM = generateComTeam("N01COM", "Community Manager Team") + val COM_UNALLOCATED = StaffGenerator.generate("Unallocated", "N01COMU") + val CASE_COMPLEX = generate( + "C246139", + "James", + "Brown", + LocalDate.of(1979, 3, 12), + "John", + "Jack", + "A5671YZ", + ReferenceDataGenerator.GENDER_MALE, + ReferenceDataGenerator.ETHNICITY_WHITE, + ReferenceDataGenerator.NATIONALITY_BRITISH, + ReferenceDataGenerator.RELIGION_OTHER, + ReferenceDataGenerator.GENDER_IDENTITY_PNS, + currentExclusion = true, + currentRestriction = true + ) + val CASE_SIMPLE = generate("S517283", "Teresa", "Green", LocalDate.of(1987, 8, 2)) + + fun generate( + crn: String, + forename: String, + surname: String, + dateOfBirth: LocalDate, + secondName: String? = null, + thirdName: String? = null, + nomsId: String? = null, + gender: ReferenceData? = null, + ethnicity: ReferenceData? = null, + nationality: ReferenceData? = null, + religion: ReferenceData? = null, + genderIdentity: ReferenceData? = null, + currentExclusion: Boolean = false, + currentRestriction: Boolean = false, + softDeleted: Boolean = false, + id: Long = IdGenerator.getAndIncrement() + ) = ProbationCase( + crn, + nomsId, + forename, + secondName, + thirdName, + surname, + dateOfBirth, + gender, + ethnicity, + nationality, + religion, + genderIdentity, + currentExclusion, + currentRestriction, + listOf(), + softDeleted, + id + ) + + fun generateComTeam(code: String, description: String, id: Long = IdGenerator.getAndIncrement()) = + CommunityManagerTeam(code, description, id) + + fun generateManager( + pc: ProbationCase, + team: CommunityManagerTeam = COM_TEAM, + active: Boolean = true, + softDeleted: Boolean = false, + id: Long = IdGenerator.getAndIncrement() + ) = CommunityManager(pc, team, active, softDeleted, id) +} + +fun ProbationCase.asPerson() = PersonGenerator.generate(crn, id) +fun CommunityManagerTeam.asTeam() = Team(id, code, description, COM_PROVIDER, null) +fun CommunityManager.asPersonManager() = + PersonManagerGenerator.generate(person.asPerson(), COM_TEAM.asTeam(), COM_UNALLOCATED, id) diff --git a/projects/approved-premises-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/ReferenceDataGenerator.kt b/projects/approved-premises-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/ReferenceDataGenerator.kt index 0d4b8fd060..4f8d74477e 100644 --- a/projects/approved-premises-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/ReferenceDataGenerator.kt +++ b/projects/approved-premises-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/ReferenceDataGenerator.kt @@ -3,9 +3,18 @@ package uk.gov.justice.digital.hmpps.data.generator import uk.gov.justice.digital.hmpps.data.generator.DatasetGenerator.ADDRESS_STATUS import uk.gov.justice.digital.hmpps.data.generator.DatasetGenerator.ADDRESS_TYPE import uk.gov.justice.digital.hmpps.data.generator.DatasetGenerator.ALL_DATASETS +import uk.gov.justice.digital.hmpps.data.generator.DatasetGenerator.ETHNICITY +import uk.gov.justice.digital.hmpps.data.generator.DatasetGenerator.GENDER +import uk.gov.justice.digital.hmpps.data.generator.DatasetGenerator.GENDER_IDENTITY import uk.gov.justice.digital.hmpps.data.generator.DatasetGenerator.HOSTEL_CODE +import uk.gov.justice.digital.hmpps.data.generator.DatasetGenerator.NATIONALITY +import uk.gov.justice.digital.hmpps.data.generator.DatasetGenerator.REGISTER_CATEGORY +import uk.gov.justice.digital.hmpps.data.generator.DatasetGenerator.REGISTER_LEVEL +import uk.gov.justice.digital.hmpps.data.generator.DatasetGenerator.RELIGION import uk.gov.justice.digital.hmpps.integrations.delius.approvedpremises.referral.entity.MoveOnCategory import uk.gov.justice.digital.hmpps.integrations.delius.approvedpremises.referral.entity.ReferralSource +import uk.gov.justice.digital.hmpps.integrations.delius.person.registration.entity.Category +import uk.gov.justice.digital.hmpps.integrations.delius.person.registration.entity.Level import uk.gov.justice.digital.hmpps.integrations.delius.person.registration.entity.RegisterType import uk.gov.justice.digital.hmpps.integrations.delius.referencedata.Dataset import uk.gov.justice.digital.hmpps.integrations.delius.referencedata.DatasetCode @@ -32,12 +41,25 @@ object ReferenceDataGenerator { val OTHER_REFERRAL_SOURCE = generateReferralSource("OTH") val MC05 = generateMoveOnCategory("MC05") - val REGISTER_TYPES = RegisterType.Code.values() - .map { RegisterType(it.value, IdGenerator.getAndIncrement()) } + val REGISTER_TYPES = RegisterType.Code.entries + .map { RegisterType(it.value, "Description of ${it.value}", IdGenerator.getAndIncrement()) } .associateBy { it.code } val REFERRAL_COMPLETED = generate("APRC", ALL_DATASETS[DatasetCode.NSI_OUTCOME]!!.id) + val ETHNICITY_WHITE = generate("W1", ETHNICITY.id, "White: British/English/Welsh/Scottish/Northern Irish") + val GENDER_MALE = generate("M", GENDER.id, "Male") + val GENDER_IDENTITY_PNS = generate("GIRF", GENDER_IDENTITY.id, "Prefer not to say") + val NATIONALITY_BRITISH = generate("BRIT", NATIONALITY.id, "British") + val RELIGION_OTHER = generate("OTH", RELIGION.id, "Other") + + val REGISTER_CATEGORIES = Category.entries.map { + generate(it.name, REGISTER_CATEGORY.id, "MAPPA Category ${it.name}") + }.associateBy { it.code } + val REGISTER_LEVELS: Map = Level.entries.map { + generate(it.name, REGISTER_LEVEL.id, "MAPPA Level ${it.name}") + }.associateBy { it.code } + fun generate( code: String, datasetId: Long, @@ -45,7 +67,7 @@ object ReferenceDataGenerator { id: Long = IdGenerator.getAndIncrement() ) = ReferenceData(id, code, description, datasetId) - fun all() = listOf( + fun all(): List = listOf( OWNER_ADDRESS_TYPE, AP_ADDRESS_TYPE, MAIN_ADDRESS_STATUS, @@ -61,19 +83,30 @@ object ReferenceDataGenerator { RISK_UNKNOWN, ORDER_EXPIRED, NON_ARRIVAL, - REFERRAL_COMPLETED - ) + REFERRAL_COMPLETED, + ETHNICITY_WHITE, + GENDER_MALE, + GENDER_IDENTITY_PNS, + NATIONALITY_BRITISH, + RELIGION_OTHER + ) + REGISTER_CATEGORIES.values + REGISTER_LEVELS.values fun generateReferralSource(code: String, id: Long = IdGenerator.getAndIncrement()) = ReferralSource(id, code) fun generateMoveOnCategory(code: String, id: Long = IdGenerator.getAndIncrement()) = MoveOnCategory(id, code) } object DatasetGenerator { - val ALL_DATASETS = DatasetCode.values().map { Dataset(IdGenerator.getAndIncrement(), it) }.associateBy { it.code } + val ALL_DATASETS = DatasetCode.entries.map { Dataset(IdGenerator.getAndIncrement(), it) }.associateBy { it.code } val ADDRESS_TYPE = ALL_DATASETS[DatasetCode.ADDRESS_TYPE]!! val ADDRESS_STATUS = ALL_DATASETS[DatasetCode.ADDRESS_STATUS]!! val HOSTEL_CODE = ALL_DATASETS[DatasetCode.HOSTEL_CODE]!! val STAFF_GRADE = ALL_DATASETS[DatasetCode.STAFF_GRADE]!! - + val GENDER = ALL_DATASETS[DatasetCode.GENDER]!! + val GENDER_IDENTITY = ALL_DATASETS[DatasetCode.GENDER_IDENTITY]!! + val ETHNICITY = ALL_DATASETS[DatasetCode.ETHNICITY]!! + val NATIONALITY = ALL_DATASETS[DatasetCode.NATIONALITY]!! + val RELIGION = ALL_DATASETS[DatasetCode.RELIGION]!! + val REGISTER_CATEGORY = ALL_DATASETS[DatasetCode.REGISTER_CATEGORY]!! + val REGISTER_LEVEL = ALL_DATASETS[DatasetCode.REGISTER_LEVEL]!! fun all() = ALL_DATASETS.values } diff --git a/projects/approved-premises-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/TeamGenerator.kt b/projects/approved-premises-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/TeamGenerator.kt index 3a3bce63d3..2d9c9436fb 100644 --- a/projects/approved-premises-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/TeamGenerator.kt +++ b/projects/approved-premises-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/TeamGenerator.kt @@ -15,15 +15,20 @@ object TeamGenerator { fun generate( approvedPremises: ApprovedPremises? = null, - code: String = "N54${teamCodeGenerator.getAndIncrement().toString().padStart(3, '0')}" + code: String = "N54${teamCodeGenerator.getAndIncrement().toString().padStart(3, '0')}", + description: String = "Description of Team $code" ) = Team( id = IdGenerator.getAndIncrement(), code = code, + description = description, probationArea = ProbationAreaGenerator.DEFAULT, approvedPremises = approvedPremises ) } object ProbationAreaGenerator { - val DEFAULT = ProbationArea(IdGenerator.getAndIncrement(), "N54") + val DEFAULT = generate("N54") + + fun generate(code: String, id: Long = IdGenerator.getAndIncrement()) = + ProbationArea(id, code) } diff --git a/projects/approved-premises-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/ProbationCaseIntegrationTest.kt b/projects/approved-premises-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/ProbationCaseIntegrationTest.kt new file mode 100644 index 0000000000..339e3a50bc --- /dev/null +++ b/projects/approved-premises-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/ProbationCaseIntegrationTest.kt @@ -0,0 +1,86 @@ +package uk.gov.justice.digital.hmpps + +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.module.kotlin.readValue +import com.github.tomakehurst.wiremock.WireMockServer +import org.hamcrest.MatcherAssert.assertThat +import org.hamcrest.Matchers.equalTo +import org.junit.jupiter.api.Assertions.assertTrue +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.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT +import org.springframework.test.web.servlet.MockMvc +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post +import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status +import uk.gov.justice.digital.hmpps.data.generator.ProbationCaseGenerator +import uk.gov.justice.digital.hmpps.model.CaseDetail +import uk.gov.justice.digital.hmpps.model.CaseSummaries +import uk.gov.justice.digital.hmpps.model.Name +import uk.gov.justice.digital.hmpps.security.withOAuth2Token +import java.time.LocalDate + +@AutoConfigureMockMvc +@SpringBootTest(webEnvironment = RANDOM_PORT) +class ProbationCaseIntegrationTest { + @Autowired + lateinit var mockMvc: MockMvc + + @Autowired + lateinit var wireMockServer: WireMockServer + + @Autowired + lateinit var objectMapper: ObjectMapper + + @Test + fun `case summaries are correctly returned`() { + val complex = ProbationCaseGenerator.CASE_COMPLEX + val simple = ProbationCaseGenerator.CASE_SIMPLE + val response = mockMvc + .perform( + post("/probation-cases/summaries") + .contentType("application/json") + .content(objectMapper.writeValueAsString(listOf(complex.crn, simple.crn))) + .withOAuth2Token(wireMockServer) + ) + .andExpect(status().isOk) + .andReturn().response.contentAsString + + val summaries = objectMapper.readValue(response) + assertThat(summaries.cases.size, equalTo(2)) + assertThat(summaries.cases.map { it.crn }.sorted(), equalTo(listOf(complex.crn, simple.crn).sorted())) + val complexCase = summaries.cases.first { it.crn == complex.crn } + assertThat(complexCase.name, equalTo(Name("James", "Brown", listOf("John", "Jack")))) + assertThat(complexCase.dateOfBirth, equalTo(LocalDate.of(1979, 3, 12))) + assertTrue(complexCase.currentExclusion) + assertTrue(complexCase.currentRestriction) + } + + @Test + fun `case details are correctly returned`() { + val case = ProbationCaseGenerator.CASE_COMPLEX + val response = mockMvc + .perform( + get("/probation-cases/${case.crn}/details") + .contentType("application/json") + .withOAuth2Token(wireMockServer) + ) + .andExpect(status().isOk) + .andReturn().response.contentAsString + + val detail = objectMapper.readValue(response) + assertThat(detail.case.name, equalTo(Name("James", "Brown", listOf("John", "Jack")))) + assertThat(detail.case.dateOfBirth, equalTo(LocalDate.of(1979, 3, 12))) + assertTrue(detail.case.currentExclusion) + assertTrue(detail.case.currentRestriction) + assertThat(detail.mappaDetail?.category, equalTo(3)) + assertThat(detail.mappaDetail?.level, equalTo(2)) + assertThat(detail.registrations.map { it.description }, equalTo(listOf("Description of ARSO"))) + val mainOffence = detail.offences.first { it.main } + assertThat(mainOffence.description, equalTo("Offence One")) + val otherOffence = detail.offences.first { !it.main } + assertThat(otherOffence.description, equalTo("Offence Two")) + } +} diff --git a/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/controller/CaseController.kt b/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/controller/CaseController.kt new file mode 100644 index 0000000000..9699b4cf6d --- /dev/null +++ b/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/controller/CaseController.kt @@ -0,0 +1,28 @@ +package uk.gov.justice.digital.hmpps.controller + +import jakarta.validation.constraints.Size +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.RequestBody +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RequestMethod +import org.springframework.web.bind.annotation.RestController +import uk.gov.justice.digital.hmpps.model.CaseDetail +import uk.gov.justice.digital.hmpps.model.CaseSummaries +import uk.gov.justice.digital.hmpps.service.CaseService + +@RestController +@RequestMapping("probation-cases") +class CaseController(private val caseService: CaseService) { + + @PreAuthorize("hasRole('ROLE_APPROVED_PREMISES_STAFF')") + @RequestMapping(value = ["/summaries"], method = [RequestMethod.GET, RequestMethod.POST]) + fun getCaseSummaries( + @Size(min = 1, max = 500, message = "Please provide between 1 and 500 crns") @RequestBody crns: List + ): CaseSummaries = caseService.getCaseSummaries(crns) + + @PreAuthorize("hasRole('ROLE_APPROVED_PREMISES_STAFF')") + @GetMapping("/{crn}/details") + fun getCaseDetail(@PathVariable crn: String): CaseDetail = caseService.getCaseDetail(crn) +} diff --git a/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/controller/UserController.kt b/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/controller/UserController.kt new file mode 100644 index 0000000000..3be10f48ed --- /dev/null +++ b/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/controller/UserController.kt @@ -0,0 +1,22 @@ +package uk.gov.justice.digital.hmpps.controller + +import jakarta.validation.constraints.Size +import org.springframework.security.access.prepost.PreAuthorize +import org.springframework.web.bind.annotation.RequestBody +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RequestMethod +import org.springframework.web.bind.annotation.RequestParam +import org.springframework.web.bind.annotation.RestController +import uk.gov.justice.digital.hmpps.service.UserAccess +import uk.gov.justice.digital.hmpps.service.UserAccessService + +@RestController +@RequestMapping("users") +class UserController(private val uas: UserAccessService) { + @PreAuthorize("hasRole('APPROVED_PREMISES_STAFF')") + @RequestMapping("access", method = [RequestMethod.GET, RequestMethod.POST]) + fun userAccessCheck( + @RequestParam(required = false) username: String?, + @Size(min = 1, max = 500, message = "Please provide between 1 and 500 crns") @RequestBody crns: List + ): UserAccess = username?.let { uas.userAccessFor(it, crns) } ?: uas.checkLimitedAccessFor(crns) +} diff --git a/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/approvedpremises/referral/entity/Referral.kt b/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/approvedpremises/referral/entity/Referral.kt index 6982718899..081ba58441 100644 --- a/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/approvedpremises/referral/entity/Referral.kt +++ b/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/approvedpremises/referral/entity/Referral.kt @@ -13,6 +13,7 @@ import jakarta.persistence.SequenceGenerator import jakarta.persistence.Table import jakarta.persistence.Version import org.hibernate.annotations.Immutable +import org.hibernate.annotations.Where import org.hibernate.type.YesNoConverter import org.springframework.data.annotation.CreatedBy import org.springframework.data.annotation.CreatedDate @@ -155,6 +156,7 @@ class ReferralSource( @Entity @Immutable @Table +@Where(clause = "active_flag = 1 and soft_deleted = 0") class Event( @Id @Column(name = "event_id") @@ -164,7 +166,13 @@ class Event( val number: String, @Column(name = "offender_id") - val personId: Long + val personId: Long, + + @Column(name = "active_flag", columnDefinition = "number") + val active: Boolean, + + @Column(columnDefinition = "number") + val softDeleted: Boolean ) interface ReferralRepository : JpaRepository { diff --git a/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/person/ProbationCase.kt b/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/person/ProbationCase.kt new file mode 100644 index 0000000000..4bca188933 --- /dev/null +++ b/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/person/ProbationCase.kt @@ -0,0 +1,129 @@ +package uk.gov.justice.digital.hmpps.integrations.delius.person + +import jakarta.persistence.Column +import jakarta.persistence.Entity +import jakarta.persistence.Id +import jakarta.persistence.JoinColumn +import jakarta.persistence.ManyToOne +import jakarta.persistence.OneToMany +import jakarta.persistence.Table +import org.hibernate.annotations.Immutable +import org.hibernate.annotations.Where +import org.springframework.data.jpa.repository.EntityGraph +import org.springframework.data.jpa.repository.JpaRepository +import uk.gov.justice.digital.hmpps.integrations.delius.referencedata.ReferenceData +import java.time.LocalDate + +@Immutable +@Entity +@Table(name = "offender") +@Where(clause = "soft_deleted = 0") +class ProbationCase( + + @Column(columnDefinition = "char(7)") + val crn: String, + + @Column(name = "noms_number", columnDefinition = "char(7)") + val nomsId: String?, + + @Column(name = "first_name") + val forename: String, + + @Column(name = "second_name") + val secondName: String?, + + @Column(name = "third_name") + val thirdName: String?, + + @Column(name = "surname") + val surname: String, + + @Column(name = "date_of_birth_date") + val dateOfBirth: LocalDate, + + @ManyToOne + @JoinColumn(name = "gender_id") + val gender: ReferenceData?, + + @ManyToOne + @JoinColumn(name = "ethnicity_id") + val ethnicity: ReferenceData?, + + @ManyToOne + @JoinColumn(name = "nationality_id") + val nationality: ReferenceData?, + + @ManyToOne + @JoinColumn(name = "religion_id") + val religion: ReferenceData?, + + @ManyToOne + @JoinColumn(name = "gender_identity_id") + val genderIdentity: ReferenceData?, + + @Column(columnDefinition = "number") + val currentExclusion: Boolean?, + + @Column(columnDefinition = "number") + val currentRestriction: Boolean?, + + @OneToMany(mappedBy = "person") + val communityManagers: List, + + @Column(columnDefinition = "number") + val softDeleted: Boolean, + + @Id + @Column(name = "offender_id") + val id: Long +) { + fun currentManager() = communityManagers.first() +} + +@Entity +@Immutable +@Table(name = "offender_manager") +@Where(clause = "active_flag = 1 and soft_deleted = 0") +class CommunityManager( + + @ManyToOne + @JoinColumn(name = "offender_id") + val person: ProbationCase, + + @ManyToOne + @JoinColumn(name = "team_id") + val team: CommunityManagerTeam, + + @Column(name = "active_flag", columnDefinition = "number") + val active: Boolean = true, + + @Column(columnDefinition = "number") + val softDeleted: Boolean = false, + + @Id + @Column(name = "offender_manager_id") + val id: Long +) + +@Entity +@Immutable +@Table(name = "team") +class CommunityManagerTeam( + + @Column(columnDefinition = "char(6)") + val code: String, + + val description: String, + + @Id + @Column(name = "team_id") + val id: Long +) + +interface ProbationCaseRepository : JpaRepository { + @EntityGraph(attributePaths = ["gender", "ethnicity", "nationality", "religion", "genderIdentity", "communityManagers.team"]) + fun findByCrnIn(crns: List): List + + @EntityGraph(attributePaths = ["gender", "ethnicity", "nationality", "religion", "genderIdentity", "communityManagers.team"]) + fun findByCrn(crn: String): ProbationCase? +} diff --git a/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/person/offence/entity/Offence.kt b/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/person/offence/entity/Offence.kt new file mode 100644 index 0000000000..3e8e467ef9 --- /dev/null +++ b/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/person/offence/entity/Offence.kt @@ -0,0 +1,103 @@ +package uk.gov.justice.digital.hmpps.integrations.delius.person.offence.entity + +import jakarta.persistence.Column +import jakarta.persistence.Entity +import jakarta.persistence.Id +import jakarta.persistence.JoinColumn +import jakarta.persistence.ManyToOne +import jakarta.persistence.OneToOne +import jakarta.persistence.Table +import org.hibernate.annotations.Immutable +import org.hibernate.annotations.Where +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.data.jpa.repository.Query +import uk.gov.justice.digital.hmpps.integrations.delius.approvedpremises.referral.entity.Event +import java.time.LocalDate + +interface CaseOffence { + val description: String + val date: LocalDate + val main: Boolean + val eventNumber: String +} + +@Immutable +@Table(name = "main_offence") +@Entity +@Where(clause = "soft_deleted = 0") +class MainOffence( + + @OneToOne + @JoinColumn(name = "event_id") + val event: Event, + + @JoinColumn(name = "offence_id") + @ManyToOne + val offence: Offence, + + @Column(name = "offence_date") + val date: LocalDate, + + @Column(columnDefinition = "number") + val softDeleted: Boolean, + + @Id + @Column(name = "main_offence_id") + val id: Long +) + +@Immutable +@Table(name = "additional_offence") +@Entity +@Where(clause = "soft_deleted = 0") +class AdditionalOffence( + + @ManyToOne + @JoinColumn(name = "event_id") + val event: Event, + + @JoinColumn(name = "offence_id") + @ManyToOne + val offence: Offence, + + @Column(name = "offence_date") + val date: LocalDate, + + @Column(columnDefinition = "number") + val softDeleted: Boolean, + + @Id + @Column(name = "additional_offence_id") + val id: Long +) + +@Immutable +@Table(name = "r_offence") +@Entity +class Offence( + + @Column(columnDefinition = "char(5)") + val code: String, + + @Column + val description: String, + + @Id + @Column(name = "offence_id") + val id: Long +) + +interface MainOffenceRepository : JpaRepository { + @Query( + """ + select mo.offence.description as description, mo.date as date, true as main, mo.event.number as eventNumber + from MainOffence mo + where mo.event.personId = :personId + union all + select ao.offence.description, ao.date, false, ao.event.number + from AdditionalOffence ao + where ao.event.personId = :personId + """ + ) + fun findOffencesFor(personId: Long): List +} diff --git a/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/person/registration/entity/Registration.kt b/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/person/registration/entity/Registration.kt index 06e95048b2..1776b95431 100644 --- a/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/person/registration/entity/Registration.kt +++ b/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/person/registration/entity/Registration.kt @@ -8,7 +8,11 @@ import jakarta.persistence.ManyToOne import jakarta.persistence.Table import org.hibernate.annotations.Immutable import org.hibernate.annotations.Where +import org.springframework.data.jpa.repository.EntityGraph import org.springframework.data.jpa.repository.JpaRepository +import uk.gov.justice.digital.hmpps.integrations.delius.referencedata.ReferenceData +import java.time.LocalDate +import java.time.ZonedDateTime @Immutable @Entity @@ -23,12 +27,25 @@ class Registration( @JoinColumn(name = "register_type_id") val type: RegisterType, + @ManyToOne + @JoinColumn(name = "register_category_id") + val category: ReferenceData?, + + @ManyToOne + @JoinColumn(name = "register_level_id") + val level: ReferenceData?, + + @Column(name = "registration_date") + val date: LocalDate, + @Column(columnDefinition = "number") val softDeleted: Boolean, @Column(columnDefinition = "number") val deregistered: Boolean, + val lastUpdatedDatetime: ZonedDateTime, + @Id @Column(name = "registration_id") val id: Long @@ -42,16 +59,25 @@ class RegisterType( @Column val code: String, + val description: String, + @Id @Column(name = "register_type_id") val id: Long ) { enum class Code(val value: String) { GANG_AFFILIATION("STRG"), - SEX_OFFENCE("ARSO") + SEX_OFFENCE("ARSO"), + MAPPA("MAPP") } } interface RegistrationRepository : JpaRepository { fun existsByPersonIdAndTypeCode(personId: Long, code: String): Boolean + + @EntityGraph(attributePaths = ["type", "category", "level"]) + fun findByPersonId(personId: Long): List } + +enum class Category(val number: Int) { X9(0), M1(1), M2(2), M3(3), M4(4) } +enum class Level(val number: Int) { M0(0), M1(1), M2(2), M3(3) } diff --git a/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/referencedata/ReferenceData.kt b/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/referencedata/ReferenceData.kt index 6af798a7ad..5fa3bf5bcb 100644 --- a/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/referencedata/ReferenceData.kt +++ b/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/referencedata/ReferenceData.kt @@ -47,16 +47,23 @@ enum class DatasetCode(val value: String) { AP_NON_ARRIVAL_REASON("AP NON ARRIVAL REASON"), AP_REFERRAL_CATEGORY("AP REFERRAL CATEGORY"), AP_REFERRAL_DATE_TYPE("AP REFERRAL DATE TYPE"), + ETHNICITY("ETHNICITY"), + GENDER("GENDER"), + GENDER_IDENTITY("GENDER IDENTITY"), HOSTEL_CODE("HOSTEL CODE"), + NATIONALITY("NATIONALITY"), NSI_OUTCOME("NSI OUTCOME"), REFERRAL_DECISION("REFERRAL DECISION"), + REGISTER_CATEGORY("REGISTER CATEGORY"), + REGISTER_LEVEL("REGISTER LEVEL"), + RELIGION("RELIGION/FAITH"), RISK_OF_HARM("RISK OF HARM"), SOURCE_TYPE("SOURCE TYPE"), STAFF_GRADE("OFFICER GRADE"), YES_NO("YES NO DONT KNOW"); companion object { - private val index = DatasetCode.values().associateBy { it.value } + private val index = DatasetCode.entries.associateBy { it.value } fun fromString(value: String): DatasetCode = index[value] ?: throw IllegalArgumentException("Invalid DatasetCode") } diff --git a/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/team/Team.kt b/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/team/Team.kt index 70c5891c30..a7891de080 100644 --- a/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/team/Team.kt +++ b/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/team/Team.kt @@ -21,6 +21,8 @@ class Team( @Column(name = "code", columnDefinition = "char(6)") val code: String, + val description: String, + @ManyToOne @JoinColumn(name = "probation_area_id", nullable = false) val probationArea: ProbationArea, diff --git a/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/model/CaseDetail.kt b/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/model/CaseDetail.kt new file mode 100644 index 0000000000..e1d6f9255a --- /dev/null +++ b/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/model/CaseDetail.kt @@ -0,0 +1,55 @@ +package uk.gov.justice.digital.hmpps.model + +import java.time.LocalDate +import java.time.ZonedDateTime + +data class CaseSummaries(val cases: List) + +data class CaseSummary( + val crn: String, + val nomsId: String?, + val name: Name, + val dateOfBirth: LocalDate, + val gender: String?, + val profile: Profile?, + val manager: Manager, + val currentExclusion: Boolean, + val currentRestriction: Boolean +) + +data class CaseDetail( + val case: CaseSummary, + val offences: List, + val registrations: List, + val mappaDetail: MappaDetail? +) + +data class Name(val forename: String, val surname: String, val middleNames: List) + +data class Profile( + val ethnicity: String?, + val genderIdentity: String?, + val nationality: String?, + val religion: String? +) + +data class Manager( + val team: Team +) + +data class Team( + val code: String, + val name: String +) + +data class MappaDetail( + val level: Int?, + val levelDescription: String?, + val category: Int?, + val categoryDescription: String?, + val startDate: LocalDate, + val lastUpdated: ZonedDateTime +) + +data class Offence(val description: String, val date: LocalDate, val main: Boolean, val eventNumber: String) +data class Registration(val description: String, val startDate: LocalDate) diff --git a/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/CaseService.kt b/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/CaseService.kt new file mode 100644 index 0000000000..bd3c9be7e8 --- /dev/null +++ b/projects/approved-premises-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/CaseService.kt @@ -0,0 +1,89 @@ +package uk.gov.justice.digital.hmpps.service + +import org.springframework.stereotype.Service +import uk.gov.justice.digital.hmpps.integrations.delius.person.CommunityManager +import uk.gov.justice.digital.hmpps.integrations.delius.person.ProbationCase +import uk.gov.justice.digital.hmpps.integrations.delius.person.ProbationCaseRepository +import uk.gov.justice.digital.hmpps.integrations.delius.person.offence.entity.CaseOffence +import uk.gov.justice.digital.hmpps.integrations.delius.person.offence.entity.MainOffenceRepository +import uk.gov.justice.digital.hmpps.integrations.delius.person.registration.entity.Category +import uk.gov.justice.digital.hmpps.integrations.delius.person.registration.entity.Level +import uk.gov.justice.digital.hmpps.integrations.delius.person.registration.entity.RegisterType +import uk.gov.justice.digital.hmpps.integrations.delius.person.registration.entity.Registration +import uk.gov.justice.digital.hmpps.integrations.delius.person.registration.entity.RegistrationRepository +import uk.gov.justice.digital.hmpps.model.CaseDetail +import uk.gov.justice.digital.hmpps.model.CaseSummaries +import uk.gov.justice.digital.hmpps.model.CaseSummary +import uk.gov.justice.digital.hmpps.model.Manager +import uk.gov.justice.digital.hmpps.model.MappaDetail +import uk.gov.justice.digital.hmpps.model.Name +import uk.gov.justice.digital.hmpps.model.Offence +import uk.gov.justice.digital.hmpps.model.Profile +import uk.gov.justice.digital.hmpps.model.Team + +@Service +class CaseService( + private val probationCaseRepository: ProbationCaseRepository, + private val registrationRepository: RegistrationRepository, + private val offenceRepository: MainOffenceRepository +) { + fun getCaseSummaries(crns: List): CaseSummaries = + CaseSummaries(probationCaseRepository.findByCrnIn(crns).map { it.summary() }) + + fun getCaseDetail(crn: String): CaseDetail { + val person = probationCaseRepository.findByCrn(crn) + ?: throw uk.gov.justice.digital.hmpps.exception.NotFoundException("ProbationCase", "crn", crn) + val registrations = registrationRepository.findByPersonId(person.id) + val offences = offenceRepository.findOffencesFor(person.id) + return person.summary().withDetail(offences, registrations) + } +} + +fun ProbationCase.summary() = CaseSummary( + crn, + nomsId, + name(), + dateOfBirth, + gender?.description, + profile(), + manager(), + currentExclusion ?: false, + currentRestriction ?: false +) + +fun CaseSummary.withDetail(offences: List, registrations: List): CaseDetail { + val regMap = registrations.groupBy { it.type.code == RegisterType.Code.MAPPA.value } + return CaseDetail(this, offences.map { it.asOffence() }, regMap.flags(), regMap.mappa()) +} + +fun ProbationCase.name() = Name(forename, surname, listOfNotNull(secondName, thirdName)) +fun ProbationCase.profile() = + Profile(ethnicity?.description, genderIdentity?.description, nationality?.description, religion?.description) + +fun ProbationCase.manager(): Manager = + with(currentManager()) { + Manager(team()) + } + +fun CommunityManager.team() = Team(team.code, team.description) + +fun CaseOffence.asOffence() = Offence(description, date, main, eventNumber) + +fun Registration.asRegistration() = uk.gov.justice.digital.hmpps.model.Registration(type.description, date) +fun Registration.asMappa() = MappaDetail( + level?.code?.toMappaLevel(), + level?.description, + category?.code?.toMappaCategory(), + category?.description, + date, + lastUpdatedDatetime +) + +fun String.toMappaLevel() = Level.entries.find { it.name == this }?.number + ?: throw IllegalStateException("Unexpected MAPPA level: $this") + +fun String.toMappaCategory() = Category.entries.find { it.name == this }?.number + ?: throw IllegalStateException("Unexpected MAPPA category: $this") + +fun Map>.mappa() = get(true)?.firstOrNull()?.asMappa() +fun Map>.flags() = get(false)?.map { it.asRegistration() } ?: listOf() diff --git a/projects/approved-premises-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/controller/UserControllerTest.kt b/projects/approved-premises-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/controller/UserControllerTest.kt new file mode 100644 index 0000000000..ad7d7dd5cf --- /dev/null +++ b/projects/approved-premises-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/controller/UserControllerTest.kt @@ -0,0 +1,64 @@ +package uk.gov.justice.digital.hmpps.controller + +import org.hamcrest.MatcherAssert.assertThat +import org.hamcrest.Matchers.equalTo +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +import org.mockito.InjectMocks +import org.mockito.Mock +import org.mockito.junit.jupiter.MockitoExtension +import org.mockito.kotlin.verify +import org.mockito.kotlin.whenever +import uk.gov.justice.digital.hmpps.service.CaseAccess +import uk.gov.justice.digital.hmpps.service.UserAccess +import uk.gov.justice.digital.hmpps.service.UserAccessService + +@ExtendWith(MockitoExtension::class) +class UserControllerTest { + @Mock + internal lateinit var userAccessService: UserAccessService + + @InjectMocks + internal lateinit var userController: UserController + + @Test + fun `when username provided, calls service with username`() { + val username = "john-smith" + val crns = listOf("T123456", "T234567", "T345678") + whenever(userAccessService.userAccessFor(username, crns)).thenReturn( + UserAccess( + crns.map { + CaseAccess( + it, + userExcluded = false, + userRestricted = false + ) + } + ) + ) + + val res = userController.userAccessCheck(username, crns) + verify(userAccessService).userAccessFor(username, crns) + assertThat(res.access.size, equalTo(3)) + } + + @Test + fun `when no username provided, calls service without username`() { + val crns = listOf("N123456", "N234567", "N345678") + whenever(userAccessService.checkLimitedAccessFor(crns)).thenReturn( + UserAccess( + crns.map { + CaseAccess( + it, + userExcluded = false, + userRestricted = false + ) + } + ) + ) + + val res = userController.userAccessCheck(null, crns) + verify(userAccessService).checkLimitedAccessFor(crns) + assertThat(res.access.size, equalTo(3)) + } +}