Skip to content

Commit

Permalink
PI-2065: Updated caseload api (#3669)
Browse files Browse the repository at this point in the history
* PI-2065: Updated caseload api
  • Loading branch information
pmcphee77 authored Apr 23, 2024
1 parent 325fef7 commit 6a18b23
Show file tree
Hide file tree
Showing 13 changed files with 351 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ object ContactGenerator {
val DEFAULT_STAFF = generateStaff("N01BDT1", "John", "Smith", emptyList())
val STAFF_1 = generateStaff("N01BDT2", "Jim", "Brown", emptyList())

val DEFAULT_TEAM = generateTeam(code = "TEAM1", description = "Main Team", staff = listOf(DEFAULT_STAFF, STAFF_1))
val DEFAULT_TEAM = generateTeam(code = "TEAM11", description = "Main Team", staff = listOf(DEFAULT_STAFF, STAFF_1))

val USER = User(
id = IdGenerator.getAndIncrement(),
Expand Down Expand Up @@ -251,7 +251,7 @@ fun generateTeam(
description: String = "Description of $code",
id: Long = IdGenerator.getAndIncrement(),
staff: List<Staff>,
) = Team(id = id, code = code, description = description, staff = staff)
) = Team(id = id, code = code, description = description, staff = staff, provider = DEFAULT_PROVIDER)

fun generateStaff(
code: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,19 @@ import org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDO
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status
import uk.gov.justice.digital.hmpps.api.model.user.User
import uk.gov.justice.digital.hmpps.api.model.Name
import uk.gov.justice.digital.hmpps.api.model.user.StaffCaseload
import uk.gov.justice.digital.hmpps.api.model.user.TeamStaff
import uk.gov.justice.digital.hmpps.api.model.user.UserTeam
import uk.gov.justice.digital.hmpps.data.generator.ContactGenerator.DEFAULT_PROVIDER
import uk.gov.justice.digital.hmpps.data.generator.ContactGenerator.DEFAULT_STAFF
import uk.gov.justice.digital.hmpps.data.generator.ContactGenerator.DEFAULT_TEAM
import uk.gov.justice.digital.hmpps.data.generator.ContactGenerator.STAFF_1
import uk.gov.justice.digital.hmpps.data.generator.ContactGenerator.USER
import uk.gov.justice.digital.hmpps.data.generator.ContactGenerator.USER_1
import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator.OVERVIEW
import uk.gov.justice.digital.hmpps.data.generator.personalDetails.PersonDetailsGenerator.PERSONAL_DETAILS
import uk.gov.justice.digital.hmpps.service.name

import uk.gov.justice.digital.hmpps.test.MockMvcExtensions.contentAsJson
import uk.gov.justice.digital.hmpps.test.MockMvcExtensions.withToken

Expand All @@ -32,48 +37,84 @@ internal class UserIntegrationTest {

val person = USER
val res = mockMvc
.perform(get("/caseload/${person.username}").withToken())
.perform(get("/caseload/user/${person.username}").withToken())
.andExpect(status().isOk)
.andReturn().response.contentAsJson<User>()
.andReturn().response.contentAsJson<StaffCaseload>()

assertThat(res.cases[0].crn, equalTo(OVERVIEW.crn))
assertThat(res.cases[0].caseName, equalTo(OVERVIEW.name()))
assertThat(res.teams[0].description, equalTo(DEFAULT_TEAM.description))
assertThat(res.teams[0].cases[0].crn, equalTo(OVERVIEW.crn))
assertThat(res.teams[0].cases[0].caseName, equalTo(OVERVIEW.name()))
assertThat(res.teams[0].cases[1].crn, equalTo(PERSONAL_DETAILS.crn))
assertThat(res.teams[0].cases[1].caseName, equalTo(PERSONAL_DETAILS.name()))
assertThat(res.provider, equalTo(DEFAULT_PROVIDER.description))
assertThat(res.caseload[0].crn, equalTo(OVERVIEW.crn))
assertThat(res.caseload[0].caseName, equalTo(OVERVIEW.name()))
}

@Test
fun `all caseload activity is for another user`() {

val person = USER_1
val res = mockMvc
.perform(get("/caseload/${person.username}").withToken())
.perform(get("/caseload/user/${person.username}").withToken())
.andExpect(status().isOk)
.andReturn().response.contentAsJson<User>()
.andReturn().response.contentAsJson<StaffCaseload>()

assertThat(res.cases[0].crn, equalTo(PERSONAL_DETAILS.crn))
assertThat(res.cases[0].caseName, equalTo(PERSONAL_DETAILS.name()))
assertThat(res.teams[0].description, equalTo(DEFAULT_TEAM.description))
assertThat(res.teams[0].cases[1].crn, equalTo(PERSONAL_DETAILS.crn))
assertThat(res.teams[0].cases[1].caseName, equalTo(PERSONAL_DETAILS.name()))
assertThat(res.teams[0].cases[0].crn, equalTo(OVERVIEW.crn))
assertThat(res.teams[0].cases[0].caseName, equalTo(OVERVIEW.name()))
assertThat(res.provider, equalTo(DEFAULT_PROVIDER.description))
assertThat(res.caseload[0].crn, equalTo(PERSONAL_DETAILS.crn))
assertThat(res.caseload[0].caseName, equalTo(PERSONAL_DETAILS.name()))
}

@Test
fun `not found status returned`() {
mockMvc
.perform(get("/caseload/invalidusername").withToken())
.perform(get("/caseload/user/invalidusername").withToken())
.andExpect(status().isNotFound)
}

@Test
fun `unauthorized status returned`() {
mockMvc
.perform(get("/caseload/invalidusername"))
.perform(get("/caseload/user/invalidusername"))
.andExpect(status().isUnauthorized)
}

@Test
fun `teams for a user`() {

val person = USER_1
val res = mockMvc
.perform(get("/caseload/user/${person.username}/teams").withToken())
.andExpect(status().isOk)
.andReturn().response.contentAsJson<UserTeam>()

assertThat(res.provider, equalTo(DEFAULT_PROVIDER.description))
assertThat(res.teams[0].description, equalTo(DEFAULT_TEAM.description))
assertThat(res.teams[0].code.trim(), equalTo(DEFAULT_TEAM.code.trim()))
}

@Test
fun `staff for a team`() {

val code = DEFAULT_TEAM.code.trim()
val res = mockMvc
.perform(get("/caseload/team/${code}/staff").withToken())
.andExpect(status().isOk)
.andReturn().response.contentAsJson<TeamStaff>()

assertThat(res.provider, equalTo(DEFAULT_PROVIDER.description))
assertThat(res.staff[0].code.trim(), equalTo(DEFAULT_STAFF.code.trim()))
assertThat(res.staff[0].name, equalTo(Name(forename = DEFAULT_STAFF.forename, surname = DEFAULT_STAFF.surname)))
assertThat(res.staff[1].code.trim(), equalTo(STAFF_1.code.trim()))
assertThat(res.staff[1].name, equalTo(Name(forename = STAFF_1.forename, surname = STAFF_1.surname)))
}

@Test
fun `case load for a staffcode`() {

val person = USER_1
val res = mockMvc
.perform(get("/caseload/staff/${person.staff?.code?.trim()}").withToken())
.andExpect(status().isOk)
.andReturn().response.contentAsJson<StaffCaseload>()

assertThat(res.provider, equalTo(DEFAULT_PROVIDER.description))
assertThat(res.caseload[0].crn, equalTo(PERSONAL_DETAILS.crn))
assertThat(res.caseload[0].caseName, equalTo(PERSONAL_DETAILS.name()))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,23 @@ import uk.gov.justice.digital.hmpps.service.UserService

@RestController
@Tag(name = "Caseload Info")
@RequestMapping("/caseload/{username}")
@RequestMapping("/caseload")
@PreAuthorize("hasRole('PROBATION_API__MANAGE_A_SUPERVISION__CASE_DETAIL')")
class UserController(private val userService: UserService) {

@GetMapping
@Operation(summary = "Gets caseloads for a person and staff within their teams")
fun getCaseload(@PathVariable username: String) = userService.getUserDetails(username)
@GetMapping("/user/{username}")
@Operation(summary = "Gets caseloads for the user")
fun getUserCaseload(@PathVariable username: String) = userService.getUserCaseload(username)

@GetMapping("/user/{username}/teams")
@Operation(summary = "Gets the users teams")
fun getUserTeams(@PathVariable username: String) = userService.getUserTeams(username)

@GetMapping("/team/{teamCode}/staff")
@Operation(summary = "Gets the staff within the team")
fun getTeamStaff(@PathVariable teamCode: String) = userService.getTeamStaff(teamCode)

@GetMapping("/staff/{staffCode}")
@Operation(summary = "Gets the caseload for a staff code ")
fun getStaffCaseload(@PathVariable staffCode: String) = userService.getStaffCaseload(staffCode)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package uk.gov.justice.digital.hmpps.api.model.user

import uk.gov.justice.digital.hmpps.api.model.Name

data class Staff(
val name: Name,
val code: String
)
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package uk.gov.justice.digital.hmpps.api.model.user
import uk.gov.justice.digital.hmpps.api.model.Name

data class StaffCase(
val staff: Name,
val caseName: Name,
val crn: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package uk.gov.justice.digital.hmpps.api.model.user

import uk.gov.justice.digital.hmpps.api.model.Name

data class StaffCaseload(
val provider: String?,
val staff: Name,
val caseload: List<StaffCase>
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ package uk.gov.justice.digital.hmpps.api.model.user

data class Team(
val description: String,
val cases: List<StaffCase>
val code: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package uk.gov.justice.digital.hmpps.api.model.user

data class TeamStaff(
val provider: String?,
val staff: List<Staff>,
)
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package uk.gov.justice.digital.hmpps.api.model.user

data class User(
data class UserTeam(
val provider: String?,
val teams: List<Team>,
val cases: List<StaffCase>
)
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import jakarta.persistence.*
import org.hibernate.annotations.Immutable
import org.hibernate.annotations.SQLRestriction
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.data.jpa.repository.Query
import uk.gov.justice.digital.hmpps.exception.NotFoundException
import java.time.LocalDate

Expand All @@ -29,6 +30,23 @@ class User(
val surname: String,
)

interface UserRepository : JpaRepository<User, Long> {

@Query(
"""
select u
from User u
join fetch u.staff s
join fetch s.provider p
where upper(u.username) = upper(:username)
"""
)
fun findByUsername(username: String): User?
}

fun UserRepository.getUser(username: String) =
findByUsername(username) ?: throw NotFoundException("User", "username", username)

@Immutable
@Entity
@Table(name = "staff")
Expand Down Expand Up @@ -56,7 +74,7 @@ class Staff(
joinColumns = [JoinColumn(name = "staff_id")],
inverseJoinColumns = [JoinColumn(name = "team_id")]
)
val teams: List<Team> = emptyList(),
val teams: List<Team>,

@Id
@Column(name = "staff_id")
Expand All @@ -67,6 +85,29 @@ class Staff(
}
}

interface StaffRepository : JpaRepository<Staff, Long> {
@Query(
"""
select s.teams
from Staff s
where s.code = :staffCode
"""
)
fun findTeamsByStaffCode(staffCode: String): List<Team>

@Query(
"""
select s
from Staff s
where s.code = :staffCode
"""
)
fun findByStaffCode(staffCode: String): Staff?
}

fun StaffRepository.getStaff(staffCode: String) =
findByStaffCode(staffCode) ?: throw NotFoundException("Staff", "staffCode", staffCode)

@Entity
@Immutable
@Table(name = "team")
Expand All @@ -87,9 +128,36 @@ class Team(
joinColumns = [JoinColumn(name = "team_id")],
inverseJoinColumns = [JoinColumn(name = "staff_id")]
)
val staff: List<Staff>
val staff: List<Staff>,

@JoinColumn(name = "probation_area_id")
@ManyToOne
val provider: Provider,
)

interface TeamRepository : JpaRepository<Team, Long> {
@Query(
"""
select t.staff
from Team t
where t.code = :teamCode
"""
)
fun findStaffByTeamCode(teamCode: String): List<Staff>

@Query(
"""
select t.provider.description
from Team t
where t.code = :teamCode
"""
)
fun findProviderByTeamCode(teamCode: String): String?
}

fun TeamRepository.getProvider(teamCode: String) =
findProviderByTeamCode(teamCode) ?: throw NotFoundException("Team", "teamCode", teamCode)

@Immutable
@Entity
@Table(name = "probation_area")
Expand Down Expand Up @@ -132,6 +200,18 @@ data class Caseload(
val roleCode: String
)

interface CaseloadRepository : JpaRepository<Caseload, Long> {
@Query(
"""
select c from Caseload c
join fetch c.person p
join fetch c.team t
where c.staff.code = :staffCode
"""
)
fun findByStaffCode(staffCode: String): List<Caseload>
}

@Entity
@Immutable
@Table(name = "offender")
Expand All @@ -156,9 +236,5 @@ class CaseloadPerson(
val surname: String,
)

interface UserRepository : JpaRepository<User, Long> {
fun findUserByUsername(username: String): User?
}

fun UserRepository.getUser(username: String) =
findUserByUsername(username) ?: throw NotFoundException("User", "username", username)

Loading

0 comments on commit 6a18b23

Please sign in to comment.