diff --git a/projects/manage-supervision-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt b/projects/manage-supervision-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt index cebec85ff1..36edfa35ec 100644 --- a/projects/manage-supervision-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt +++ b/projects/manage-supervision-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt @@ -103,6 +103,7 @@ class DataLoader( OffenderManagerGenerator.STAFF_2, OffenderManagerGenerator.STAFF_USER_1, OffenderManagerGenerator.STAFF_USER_2, + OffenderManagerGenerator.STAFF_TEAM, OffenderManagerGenerator.OFFENDER_MANAGER_ACTIVE, OffenderManagerGenerator.OFFENDER_MANAGER_INACTIVE, OffenderManagerGenerator.DEFAULT_LOCATION, diff --git a/projects/manage-supervision-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/OffenderManagerGenerator.kt b/projects/manage-supervision-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/OffenderManagerGenerator.kt index fc886cebff..6fdba13523 100644 --- a/projects/manage-supervision-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/OffenderManagerGenerator.kt +++ b/projects/manage-supervision-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/OffenderManagerGenerator.kt @@ -14,10 +14,22 @@ object OffenderManagerGenerator { val STAFF_1 = Staff(IdGenerator.getAndIncrement(), "Peter", "Parker", DEFAULT_PROVIDER, null) val STAFF_2 = Staff(IdGenerator.getAndIncrement(), "Bruce", "Wayne", DEFAULT_PROVIDER, null) - val STAFF_USER_1 = StaffUser(IdGenerator.getAndIncrement(), STAFF_1, "peter-parker") - val STAFF_USER_2 = StaffUser(IdGenerator.getAndIncrement(), STAFF_2, "bwayne") + val STAFF_USER_1 = StaffUser(IdGenerator.getAndIncrement(), STAFF_1, "peter-parker", "peter", surname = "parker") + val STAFF_USER_2 = StaffUser(IdGenerator.getAndIncrement(), STAFF_2, "bwayne", "bruce", surname = "wayne") + val STAFF_TEAM = ContactStaffTeam(StaffTeamLinkId(STAFF_1.id, TEAM)) - val DEFAULT_LOCATION = Location(IdGenerator.getAndIncrement(), "B20", "1 Birmingham Street") + val DEFAULT_LOCATION = + Location( + IdGenerator.getAndIncrement(), + "B20", + "1 Birmingham Street", + "Bham House", + "1", + "Birmingham Street", + "Birmingham", + "West Midlands", + "B20 3BA" + ) val TEAM_OFFICE = TeamOfficeLink(TeamOfficeLinkId(TEAM.id, DEFAULT_LOCATION)) diff --git a/projects/manage-supervision-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/AppointmentOutcomeIntegrationTest.kt b/projects/manage-supervision-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/AppointmentOutcomeIntegrationTest.kt index ebb7122973..4ff1f7335d 100644 --- a/projects/manage-supervision-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/AppointmentOutcomeIntegrationTest.kt +++ b/projects/manage-supervision-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/AppointmentOutcomeIntegrationTest.kt @@ -18,8 +18,8 @@ import uk.gov.justice.digital.hmpps.api.model.appointment.Outcome import uk.gov.justice.digital.hmpps.api.model.appointment.User import uk.gov.justice.digital.hmpps.data.generator.AppointmentGenerator.APPOINTMENT_TYPES import uk.gov.justice.digital.hmpps.data.generator.AppointmentGenerator.ATTENDED_COMPLIED +import uk.gov.justice.digital.hmpps.data.generator.OffenderManagerGenerator.DEFAULT_LOCATION import uk.gov.justice.digital.hmpps.data.generator.OffenderManagerGenerator.STAFF_USER_1 -import uk.gov.justice.digital.hmpps.data.generator.OffenderManagerGenerator.TEAM import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator import uk.gov.justice.digital.hmpps.integrations.delius.sentence.entity.AppointmentRepository import uk.gov.justice.digital.hmpps.test.CustomMatchers.isCloseTo @@ -134,7 +134,7 @@ class AppointmentOutcomeIntegrationTest { .withToken() .withJson( CreateAppointment( - User(STAFF_USER_1.username, TEAM.description), + User(STAFF_USER_1.username, DEFAULT_LOCATION.id), CreateAppointment.Type.PlannedOfficeVisitNS, ZonedDateTime.now().plusDays(1), ZonedDateTime.now().plusDays(2), diff --git a/projects/manage-supervision-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/CreateAppointmentIntegrationTest.kt b/projects/manage-supervision-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/CreateAppointmentIntegrationTest.kt index 5462baad0f..9de8d3e1df 100644 --- a/projects/manage-supervision-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/CreateAppointmentIntegrationTest.kt +++ b/projects/manage-supervision-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/CreateAppointmentIntegrationTest.kt @@ -20,7 +20,6 @@ import uk.gov.justice.digital.hmpps.data.generator.ContactGenerator.DEFAULT_PROV import uk.gov.justice.digital.hmpps.data.generator.OffenderManagerGenerator.DEFAULT_LOCATION import uk.gov.justice.digital.hmpps.data.generator.OffenderManagerGenerator.STAFF_1 import uk.gov.justice.digital.hmpps.data.generator.OffenderManagerGenerator.STAFF_USER_1 -import uk.gov.justice.digital.hmpps.data.generator.OffenderManagerGenerator.TEAM import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator import uk.gov.justice.digital.hmpps.integrations.delius.sentence.entity.AppointmentRepository import uk.gov.justice.digital.hmpps.test.CustomMatchers.isCloseTo @@ -41,7 +40,7 @@ class CreateAppointmentIntegrationTest { @Autowired internal lateinit var appointmentRepository: AppointmentRepository - private val user = User(STAFF_USER_1.username, TEAM.description) + private val user = User(STAFF_USER_1.username, DEFAULT_LOCATION.id) private val person = PersonGenerator.PERSON_1 @@ -156,7 +155,7 @@ class CreateAppointmentIntegrationTest { } companion object { - private val user = User(STAFF_USER_1.username, TEAM.description) + private val user = User(STAFF_USER_1.username, DEFAULT_LOCATION.id) @JvmStatic fun createAppointment() = listOf( diff --git a/projects/manage-supervision-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/SentencesIntegrationTest.kt b/projects/manage-supervision-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/SentencesIntegrationTest.kt new file mode 100644 index 0000000000..890a8997f4 --- /dev/null +++ b/projects/manage-supervision-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/SentencesIntegrationTest.kt @@ -0,0 +1,87 @@ +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.* +import uk.gov.justice.digital.hmpps.data.generator.LicenceConditionGenerator.LC_WITHOUT_NOTES +import uk.gov.justice.digital.hmpps.data.generator.LicenceConditionGenerator.LC_WITH_1500_CHAR_NOTE +import uk.gov.justice.digital.hmpps.data.generator.LicenceConditionGenerator.LC_WITH_NOTES +import uk.gov.justice.digital.hmpps.data.generator.LicenceConditionGenerator.LC_WITH_NOTES_WITHOUT_ADDED_BY +import uk.gov.justice.digital.hmpps.data.generator.LicenceConditionGenerator.LIC_COND_MAIN_CAT +import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator +import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator.ACTIVE_ORDER +import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator.EVENT_1 +import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator.EVENT_2 +import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator.REQUIREMENT +import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator.REQUIREMENT_UNPAID_WORK +import uk.gov.justice.digital.hmpps.data.generator.personalDetails.PersonDetailsGenerator +import uk.gov.justice.digital.hmpps.service.toSummary +import uk.gov.justice.digital.hmpps.test.MockMvcExtensions.contentAsJson +import uk.gov.justice.digital.hmpps.test.MockMvcExtensions.withToken + +@AutoConfigureMockMvc +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +class SentencesIntegrationTest { + @Autowired + lateinit var mockMvc: MockMvc + + @Test + fun `unauthorized status returned`() { + mockMvc + .perform(MockMvcRequestBuilders.get("/sentences/X123456")) + .andExpect(MockMvcResultMatchers.status().isUnauthorized) + } + + @Test + fun `no active sentences`() { + val response = mockMvc + .perform( + MockMvcRequestBuilders.get("/sentences/${PersonDetailsGenerator.PERSONAL_DETAILS.crn}").withToken() + ) + .andExpect(MockMvcResultMatchers.status().isOk) + .andReturn().response.contentAsJson() + + val expected = MinimalSentenceOverview( + PersonDetailsGenerator.PERSONAL_DETAILS.toSummary() + ) + + assertEquals(expected, response) + } + + @Test + fun `get active sentences`() { + val response = mockMvc + .perform(MockMvcRequestBuilders.get("/sentences/${PersonGenerator.OVERVIEW.crn}").withToken()) + .andExpect(MockMvcResultMatchers.status().isOk) + .andReturn().response.contentAsJson() + + val expected = MinimalSentenceOverview( + PersonGenerator.OVERVIEW.toSummary(), + listOf( + MinimalSentence(EVENT_2.id), + MinimalSentence( + EVENT_1.id, + order = MinimalOrder(ACTIVE_ORDER.type.description, ACTIVE_ORDER.date), + licenceConditions = listOf( + MinimalLicenceCondition(LC_WITH_NOTES.id, LIC_COND_MAIN_CAT.description), + MinimalLicenceCondition(LC_WITHOUT_NOTES.id, LIC_COND_MAIN_CAT.description), + MinimalLicenceCondition(LC_WITH_NOTES_WITHOUT_ADDED_BY.id, LIC_COND_MAIN_CAT.description), + MinimalLicenceCondition(LC_WITH_1500_CHAR_NOTE.id, LIC_COND_MAIN_CAT.description) + ), + requirements = listOf( + MinimalRequirement(REQUIREMENT.id, "1 days RAR, 1 completed"), + MinimalRequirement(REQUIREMENT_UNPAID_WORK.id, "Unpaid Work - Intensive") + ) + ) + ) + ) + + assertEquals(expected, response) + } +} \ No newline at end of file diff --git a/projects/manage-supervision-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/UserLocationIntegrationTest.kt b/projects/manage-supervision-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/UserLocationIntegrationTest.kt new file mode 100644 index 0000000000..7e442745ee --- /dev/null +++ b/projects/manage-supervision-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/UserLocationIntegrationTest.kt @@ -0,0 +1,69 @@ +package uk.gov.justice.digital.hmpps + +import org.hamcrest.Matchers.equalTo +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.MockMvcResultHandlers.print +import org.springframework.test.web.servlet.result.MockMvcResultMatchers +import org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath +import uk.gov.justice.digital.hmpps.api.model.sentence.Address +import uk.gov.justice.digital.hmpps.api.model.sentence.LocationDetails +import uk.gov.justice.digital.hmpps.api.model.sentence.Name +import uk.gov.justice.digital.hmpps.api.model.sentence.UserOfficeLocation +import uk.gov.justice.digital.hmpps.data.generator.OffenderManagerGenerator.DEFAULT_LOCATION +import uk.gov.justice.digital.hmpps.data.generator.OffenderManagerGenerator.STAFF_USER_1 +import uk.gov.justice.digital.hmpps.test.MockMvcExtensions.contentAsJson +import uk.gov.justice.digital.hmpps.test.MockMvcExtensions.withToken + +@AutoConfigureMockMvc +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +class UserLocationIntegrationTest { + @Autowired + lateinit var mockMvc: MockMvc + + @Test + fun `unauthorized status returned`() { + mockMvc + .perform(MockMvcRequestBuilders.get("/user/peter-parker/locations")) + .andExpect(MockMvcResultMatchers.status().isUnauthorized) + } + + @Test + fun `user not found`() { + mockMvc.perform(MockMvcRequestBuilders.get("/user/user/locations").withToken()) + .andDo(print()) + .andExpect(MockMvcResultMatchers.status().isNotFound) + .andExpect(jsonPath("$.message", equalTo("User with username of user not found"))) + } + + @Test + fun `get user locations`() { + val response = mockMvc.perform(MockMvcRequestBuilders.get("/user/peter-parker/locations").withToken()) + .andDo(print()) + .andExpect(MockMvcResultMatchers.status().isOk) + .andReturn().response.contentAsJson() + + val expected = UserOfficeLocation( + Name(STAFF_USER_1.forename, surname = STAFF_USER_1.surname), + listOf( + LocationDetails( + DEFAULT_LOCATION.id, + DEFAULT_LOCATION.description, + Address( + DEFAULT_LOCATION.buildingNumber, + DEFAULT_LOCATION.streetName, + DEFAULT_LOCATION.townCity, + DEFAULT_LOCATION.county, + DEFAULT_LOCATION.postcode + ) + ) + ) + ) + assertEquals(expected, response) + } +} \ No newline at end of file diff --git a/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/controller/SentencesController.kt b/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/controller/SentencesController.kt new file mode 100644 index 0000000000..192f1ca114 --- /dev/null +++ b/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/controller/SentencesController.kt @@ -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.* +import uk.gov.justice.digital.hmpps.service.SentenceService + +@RestController +@Tag(name = "Sentences") +@RequestMapping("/sentences/{crn}") +@PreAuthorize("hasRole('PROBATION_API__MANAGE_A_SUPERVISION__CASE_DETAIL')") +class SentencesController(private val sentenceService: SentenceService) { + + @GetMapping + @Operation(summary = "Display active events") + fun getOverview( + @PathVariable crn: String, + @RequestParam(required = false) number: String?, + ) = sentenceService.getActiveSentences(crn) +} \ No newline at end of file diff --git a/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/controller/UserLocationController.kt b/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/controller/UserLocationController.kt new file mode 100644 index 0000000000..c11ab980ae --- /dev/null +++ b/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/controller/UserLocationController.kt @@ -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.UserLocationService + +@RestController +@Tag(name = "Locations") +@RequestMapping("/user/{username}") +@PreAuthorize("hasRole('PROBATION_API__MANAGE_A_SUPERVISION__CASE_DETAIL')") +class UserLocationController(private val userLocationService: UserLocationService) { + + @GetMapping("/locations") + @Operation(summary = "Display user locations") + fun getUserOfficeLocations(@PathVariable username: String) = userLocationService.getUserOfficeLocations(username) +} \ No newline at end of file diff --git a/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/appointment/CreateAppointment.kt b/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/appointment/CreateAppointment.kt index 059fad9c00..9a99476d67 100644 --- a/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/appointment/CreateAppointment.kt +++ b/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/appointment/CreateAppointment.kt @@ -42,7 +42,7 @@ data class CreateAppointment( data class User( val username: String, - val team: String + val locationId: Long ) data class OverlappingAppointment( diff --git a/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/overview/Order.kt b/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/overview/Order.kt index 1c702c2b59..eb27659fbc 100644 --- a/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/overview/Order.kt +++ b/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/overview/Order.kt @@ -4,7 +4,7 @@ import java.time.LocalDate data class Order( val description: String, - val length: Long?, + val length: Long? = null, val endDate: LocalDate?, val releaseDate: LocalDate? = null, val startDate: LocalDate, diff --git a/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/sentence/LicenceCondition.kt b/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/sentence/LicenceCondition.kt index 895552790a..9a5cb3a6b8 100644 --- a/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/sentence/LicenceCondition.kt +++ b/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/sentence/LicenceCondition.kt @@ -24,4 +24,9 @@ data class LicenceConditionNote( data class LicenceConditionNoteDetail( val personSummary: PersonSummary, val licenceCondition: LicenceCondition? = null +) + +data class MinimalLicenceCondition( + val id: Long, + val mainDescription: String ) \ No newline at end of file diff --git a/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/sentence/Requirement.kt b/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/sentence/Requirement.kt index 1c7cea0c53..554d87c6b5 100644 --- a/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/sentence/Requirement.kt +++ b/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/sentence/Requirement.kt @@ -16,3 +16,8 @@ data class Requirement( val notes: String?, val rar: Rar? = null ) + +data class MinimalRequirement( + val id: Long, + val description: String +) diff --git a/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/sentence/Sentence.kt b/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/sentence/Sentence.kt index c4cae7c0b9..29a07260e5 100644 --- a/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/sentence/Sentence.kt +++ b/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/sentence/Sentence.kt @@ -1,6 +1,7 @@ package uk.gov.justice.digital.hmpps.api.model.sentence import uk.gov.justice.digital.hmpps.api.model.overview.Order +import java.time.LocalDate data class Sentence( val offenceDetails: OffenceDetails, @@ -8,6 +9,19 @@ data class Sentence( val order: Order? = null, val requirements: List = listOf(), val courtDocuments: List = listOf(), - val unpaidWorkProgress: String?, + val unpaidWorkProgress: String? = null, val licenceConditions: List = listOf() -) \ No newline at end of file +) + +data class MinimalSentence( + val id: Long, + val order: MinimalOrder? = null, + val licenceConditions: List = listOf(), + val requirements: List = listOf() +) + +data class MinimalOrder( + val description: String, + val startDate: LocalDate, + val endDate: LocalDate? = null, +) diff --git a/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/sentence/SentenceOverview.kt b/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/sentence/SentenceOverview.kt index a4dfcbad94..3ad71574d5 100644 --- a/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/sentence/SentenceOverview.kt +++ b/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/sentence/SentenceOverview.kt @@ -12,3 +12,8 @@ data class SentenceSummary( val eventNumber: String, val description: String ) + +data class MinimalSentenceOverview( + val personSummary: PersonSummary, + val sentences: List = emptyList(), +) \ No newline at end of file diff --git a/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/sentence/UserOfficeLocation.kt b/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/sentence/UserOfficeLocation.kt new file mode 100644 index 0000000000..29a1e74af6 --- /dev/null +++ b/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/model/sentence/UserOfficeLocation.kt @@ -0,0 +1,26 @@ +package uk.gov.justice.digital.hmpps.api.model.sentence + +data class UserOfficeLocation( + val name: Name, + val locations: List +) + +data class Name( + val forename: String, + val middleName: String? = null, + val surname: String +) + +data class LocationDetails( + val id: Long, + val description: String, + val address: Address +) + +data class Address( + val buildingNumber: String? = null, + val streetName: String? = null, + val town: String? = null, + val county: String? = null, + val postcode: String? = null +) \ No newline at end of file diff --git a/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/sentence/entity/OffenderManager.kt b/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/sentence/entity/OffenderManager.kt index c6073acd28..c40cd12b63 100644 --- a/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/sentence/entity/OffenderManager.kt +++ b/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/sentence/entity/OffenderManager.kt @@ -79,7 +79,12 @@ class StaffUser( @Column(name = "distinguished_name") val username: String, - ) { + val forename: String, + + val forename2: String? = null, + + val surname: String +) { @Transient var email: String? = null @@ -89,26 +94,52 @@ class StaffUser( interface StaffUserRepository : JpaRepository { + @Query( + """ + SELECT u + FROM StaffUser u + WHERE UPPER(u.username) = UPPER(:username) + """ + ) + fun findByUsername(username: String): StaffUser? + @Query( """ SELECT u.id AS userId, st.id AS staffId, t.id AS teamId, st.provider.id AS providerId, l.id AS locationId FROM StaffUser u - JOIN u.staff st - JOIN st.provider - JOIN Team t ON t.provider = st.provider + JOIN u.staff st + JOIN ContactStaffTeam cst ON cst.id.staffId = st.id + JOIN Team t ON t.id = cst.id.team.id JOIN TeamOfficeLink tol ON tol.id.teamId = t.id JOIN Location l ON l = tol.id.officeLocation WHERE UPPER(u.username) = UPPER(:username) - AND UPPER(t.description) = UPPER(:teamName) + AND l.id = :locationId """ ) - fun findUserAndLocation(username: String, teamName: String): UserLocation? + fun findUserAndLocation(username: String, locationId: Long): UserLocation? + + @Query( + """ + SELECT l + FROM StaffUser u + JOIN u.staff st + JOIN ContactStaffTeam cst ON cst.id.staffId = st.id + JOIN Team t ON t.id = cst.id.team.id + JOIN TeamOfficeLink tol ON tol.id.teamId = t.id + JOIN Location l ON l = tol.id.officeLocation + WHERE u.id = :id + """ + ) + fun findUserOfficeLocations(id: Long): List } -fun StaffUserRepository.getUserAndLocation(username: String, teamName: String) = - findUserAndLocation(username, teamName) ?: throw NotFoundException( +fun StaffUserRepository.getUser(username: String) = + findByUsername(username) ?: throw NotFoundException("User", "username", username) + +fun StaffUserRepository.getUserAndLocation(username: String, locationId: Long) = + findUserAndLocation(username, locationId) ?: throw NotFoundException( "User", "username", - "$username in $teamName" + "$username in $locationId" ) interface UserLocation { @@ -160,7 +191,18 @@ class Location( val description: String, - ) + val buildingName: String?, + + val buildingNumber: String?, + + val streetName: String?, + + val townCity: String?, + + val county: String?, + + val postcode: String?, +) @Embeddable class TeamOfficeLinkId( @@ -172,3 +214,20 @@ class TeamOfficeLinkId( val officeLocation: Location ) : Serializable +@Entity +@Immutable +@Table(name = "staff_team") +class ContactStaffTeam( + @Id + val id: StaffTeamLinkId +) + +@Embeddable +class StaffTeamLinkId( + @Column(name = "staff_id") + val staffId: Long, + + @ManyToOne + @JoinColumn(name = "team_id") + val team: Team +) : Serializable diff --git a/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/LicenceConditionService.kt b/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/LicenceConditionService.kt index 40de98578c..3b9777c6dd 100644 --- a/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/LicenceConditionService.kt +++ b/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/LicenceConditionService.kt @@ -4,6 +4,7 @@ import org.springframework.stereotype.Service import uk.gov.justice.digital.hmpps.api.model.sentence.LicenceCondition import uk.gov.justice.digital.hmpps.api.model.sentence.LicenceConditionNote import uk.gov.justice.digital.hmpps.api.model.sentence.LicenceConditionNoteDetail +import uk.gov.justice.digital.hmpps.api.model.sentence.MinimalLicenceCondition import uk.gov.justice.digital.hmpps.datetime.DeliusDateFormatter import uk.gov.justice.digital.hmpps.integrations.delius.overview.entity.PersonRepository import uk.gov.justice.digital.hmpps.integrations.delius.overview.entity.getPerson @@ -40,6 +41,8 @@ fun EntityLicenceCondition.toLicenceCondition() = toLicenceConditionNote(true) ) +fun EntityLicenceCondition.toMinimalLicenceCondition() = MinimalLicenceCondition(id, mainCategory.description) + fun EntityLicenceCondition.toLicenceConditionSingleNote(noteId: Int, truncateNote: Boolean) = LicenceCondition( id, diff --git a/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/SentenceAppointmentService.kt b/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/SentenceAppointmentService.kt index 55ca69c023..fc80507971 100644 --- a/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/SentenceAppointmentService.kt +++ b/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/SentenceAppointmentService.kt @@ -33,6 +33,7 @@ class SentenceAppointmentService( private val staffUserRepository: StaffUserRepository, private val objectMapper: ObjectMapper ) : AuditableService(auditedInteractionService) { + fun createAppointment( crn: String, createAppointment: CreateAppointment @@ -44,7 +45,10 @@ class SentenceAppointmentService( checkForConflicts(createAppointment) val userAndLocation = - staffUserRepository.getUserAndLocation(createAppointment.user.username, createAppointment.user.team) + staffUserRepository.getUserAndLocation( + createAppointment.user.username, + createAppointment.user.locationId + ) val createAppointments: ArrayList = arrayListOf() createAppointment.let { diff --git a/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/SentenceService.kt b/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/SentenceService.kt index b0682efe01..f862ca058c 100644 --- a/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/SentenceService.kt +++ b/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/SentenceService.kt @@ -46,6 +46,18 @@ class SentenceService( ) } + fun getActiveSentences(crn: String): MinimalSentenceOverview { + val person = personRepository.getPerson(crn) + val activeEvents = eventRepository.findSentencesByPersonId(person.id).filter { + it.active + } + + return MinimalSentenceOverview( + personSummary = person.toSummary(), + activeEvents.map { it.toMinimalSentence() } + ) + } + fun getProbationHistory(crn: String): History { val person = personRepository.getPerson(crn) val (activeEvents, inactiveEvents) = eventRepository.findSentencesByPersonId(person.id).partition { it.active } @@ -67,6 +79,19 @@ class SentenceService( disposal?.type?.description ?: "Pre-Sentence" ) + fun Event.toMinimalSentence(): MinimalSentence = + MinimalSentence( + id, + disposal?.toMinimalOrder(), + licenceConditions = disposal?.let { + licenceConditionRepository.findAllByDisposalId(disposal.id).map { + it.toMinimalLicenceCondition() + } + } ?: emptyList(), + requirements = requirementRepository.getRequirements(id, eventNumber) + .map { it.toMinimalRequirement() }, + ) + fun Event.toSentence(crn: String): Sentence { val courtAppearance = courtAppearanceRepository.getFirstCourtAppearanceByEventIdOrderByDate(id) val additionalSentences = additionalSentenceRepository.getAllByEventId(id) @@ -114,6 +139,8 @@ class SentenceService( ) } + fun Disposal.toMinimalOrder() = MinimalOrder(type.description, date, expectedEndDate()) + fun RequirementDetails.toRequirement(): Requirement { val rar = getRar(id, code) @@ -134,6 +161,11 @@ class SentenceService( return requirement } + fun RequirementDetails.toMinimalRequirement(): MinimalRequirement { + val rar = getRar(id, code) + return MinimalRequirement(id, populateRequirementDescription(description, codeDescription, rar)) + } + fun populateRequirementDescription(description: String, codeDescription: String?, rar: Rar?): String { rar?.let { return "" + it.totalDays + " days RAR, " + it.completed + " completed" } diff --git a/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/UserLocationService.kt b/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/UserLocationService.kt new file mode 100644 index 0000000000..5c0237a5bf --- /dev/null +++ b/projects/manage-supervision-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/UserLocationService.kt @@ -0,0 +1,28 @@ +package uk.gov.justice.digital.hmpps.service + +import org.springframework.stereotype.Service +import uk.gov.justice.digital.hmpps.api.model.sentence.Address +import uk.gov.justice.digital.hmpps.api.model.sentence.LocationDetails +import uk.gov.justice.digital.hmpps.api.model.sentence.Name +import uk.gov.justice.digital.hmpps.api.model.sentence.UserOfficeLocation +import uk.gov.justice.digital.hmpps.integrations.delius.sentence.entity.Location +import uk.gov.justice.digital.hmpps.integrations.delius.sentence.entity.StaffUserRepository +import uk.gov.justice.digital.hmpps.integrations.delius.sentence.entity.getUser + +@Service +class UserLocationService(private val staffUserRepository: StaffUserRepository) { + + fun getUserOfficeLocations(username: String): UserOfficeLocation { + val user = staffUserRepository.getUser(username) + + val userLocations = staffUserRepository.findUserOfficeLocations(user.id) + + return UserOfficeLocation( + Name(user.forename, user.forename2, user.surname), + userLocations.map { it.toLocationDetails() } + ) + } + + fun Location.toLocationDetails(): LocationDetails = + LocationDetails(id, description, Address(buildingNumber, streetName, townCity, county, postcode)) +} \ No newline at end of file diff --git a/projects/manage-supervision-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/service/SentenceAppointmentServiceTest.kt b/projects/manage-supervision-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/service/SentenceAppointmentServiceTest.kt index 0a5d0e1a10..c194940217 100644 --- a/projects/manage-supervision-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/service/SentenceAppointmentServiceTest.kt +++ b/projects/manage-supervision-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/service/SentenceAppointmentServiceTest.kt @@ -16,6 +16,7 @@ import uk.gov.justice.digital.hmpps.api.model.appointment.CreateAppointment import uk.gov.justice.digital.hmpps.api.model.appointment.User import uk.gov.justice.digital.hmpps.audit.service.AuditedInteractionService import uk.gov.justice.digital.hmpps.data.generator.OffenderManagerGenerator +import uk.gov.justice.digital.hmpps.data.generator.OffenderManagerGenerator.DEFAULT_LOCATION import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator import uk.gov.justice.digital.hmpps.exception.ConflictException import uk.gov.justice.digital.hmpps.exception.InvalidRequestException @@ -63,7 +64,7 @@ class SentenceAppointmentServiceTest { private val uuid: UUID = UUID.randomUUID() - private val user = User("user", "team") + private val user = User("user", DEFAULT_LOCATION.id) @Test fun `licence and requirement id provided`() { @@ -147,6 +148,7 @@ class SentenceAppointmentServiceTest { whenever(offenderManagerRepository.findByPersonCrnAndSoftDeletedIsFalseAndActiveIsTrue(PersonGenerator.PERSON_1.crn)).thenReturn( OffenderManagerGenerator.OFFENDER_MANAGER_ACTIVE ) + val exception = assertThrows { service.createAppointment(PersonGenerator.PERSON_1.crn, appointment) } @@ -272,7 +274,7 @@ class SentenceAppointmentServiceTest { whenever(offenderManagerRepository.findByPersonCrnAndSoftDeletedIsFalseAndActiveIsTrue(PersonGenerator.PERSON_1.crn)).thenReturn( OffenderManagerGenerator.OFFENDER_MANAGER_ACTIVE ) - whenever(staffUserRepository.findUserAndLocation(appointment.user.username, appointment.user.team)) + whenever(staffUserRepository.findUserAndLocation(appointment.user.username, appointment.user.locationId)) .thenReturn(UserLoc(1, 2, 3, 4, 5)) whenever(eventSentenceRepository.existsById(appointment.eventId)).thenReturn(true) @@ -305,7 +307,7 @@ class SentenceAppointmentServiceTest { whenever(offenderManagerRepository.findByPersonCrnAndSoftDeletedIsFalseAndActiveIsTrue(PersonGenerator.PERSON_1.crn)).thenReturn( OffenderManagerGenerator.OFFENDER_MANAGER_ACTIVE ) - whenever(staffUserRepository.findUserAndLocation(appointment.user.username, appointment.user.team)) + whenever(staffUserRepository.findUserAndLocation(appointment.user.username, appointment.user.locationId)) .thenReturn(UserLoc(1, 2, 3, 4, 5)) whenever(eventSentenceRepository.existsById(appointment.eventId)).thenReturn(true)