Skip to content

Commit

Permalink
MAN-183 - add new api
Browse files Browse the repository at this point in the history
  • Loading branch information
achimber-moj committed Dec 13, 2024
1 parent 7cba623 commit 4f942ac
Show file tree
Hide file tree
Showing 7 changed files with 192 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ 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))

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
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.result.MockMvcResultHandlers.print
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.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 `get user location`() {
val response = mockMvc.perform(MockMvcRequestBuilders.get("/user/peter-parker/locations").withToken())
.andDo(print())
.andExpect(MockMvcResultMatchers.status().isOk)
.andReturn().response.contentAsJson<UserOfficeLocation>()

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)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package uk.gov.justice.digital.hmpps.api.controller

import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.tags.Tag
import org.springframework.security.access.prepost.PreAuthorize
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import uk.gov.justice.digital.hmpps.service.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)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package uk.gov.justice.digital.hmpps.api.model.sentence

data class UserOfficeLocation(
val name: Name,
val locations: List<LocationDetails>
)

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
)
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class Staff(
val user: StaffUser?
)


@Entity
@Immutable
@Table(name = "user_")
Expand All @@ -79,6 +80,11 @@ class StaffUser(
@Column(name = "distinguished_name")
val username: String,

val forename: String,

val forename2: String? = null,

val surname: String
) {
@Transient
var email: String? = null
Expand All @@ -89,6 +95,15 @@ class StaffUser(

interface StaffUserRepository : JpaRepository<StaffUser, Long> {

@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
Expand All @@ -103,8 +118,25 @@ interface StaffUserRepository : JpaRepository<StaffUser, Long> {
"""
)
fun findUserAndLocation(username: String, teamName: String): 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<Location>
}

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

fun StaffUserRepository.getUserAndLocation(username: String, teamName: String) =
findUserAndLocation(username, teamName) ?: throw NotFoundException(
"User", "username",
Expand Down Expand Up @@ -160,7 +192,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(
Expand All @@ -172,3 +215,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
Original file line number Diff line number Diff line change
@@ -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))
}

0 comments on commit 4f942ac

Please sign in to comment.