Skip to content

Commit

Permalink
PI-1991: Added schedule endpoints (#3520)
Browse files Browse the repository at this point in the history
* PI-1991: Added schedule endpoints

* PI-1991: Added schedule endpoints

* PI-1991: Added schedule endpoints

* PI-1991: Added schedule endpoints
  • Loading branch information
pmcphee77 authored Mar 22, 2024
1 parent 323e712 commit b095b8f
Show file tree
Hide file tree
Showing 21 changed files with 905 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ class DataLoader(
@Transactional
override fun onApplicationEvent(are: ApplicationReadyEvent) {

entityManager.persistAll(
ContactGenerator.DEFAULT_PROVIDER,
ContactGenerator.DEFAULT_BOROUGH,
ContactGenerator.DEFAULT_DISTRICT,
ContactGenerator.DEFAULT_STAFF,
ContactGenerator.LOCATION_BRK_1
)

entityManager.persist(PersonGenerator.OVERVIEW.gender)
entityManager.persist(UserGenerator.USER)
PersonGenerator.DISABILITIES.forEach { entityManager.persist(it.type) }
Expand Down Expand Up @@ -73,6 +81,9 @@ class DataLoader(
ContactGenerator.FIRST_NON_APPT_CONTACT,
ContactGenerator.NEXT_APPT_CONTACT,
ContactGenerator.FIRST_APPT_CONTACT,
ContactGenerator.PREVIOUS_APPT_CONTACT_ABSENT,
ContactGenerator.CONTACT_DOCUMENT_1,
ContactGenerator.CONTACT_DOCUMENT_2,
PersonGenerator.OFFENCE_1,
PersonGenerator.MAIN_OFFENCE_1,
PersonGenerator.OFFENCE_2,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,44 @@
package uk.gov.justice.digital.hmpps.data.generator

import uk.gov.justice.digital.hmpps.data.generator.ContactGenerator.DEFAULT_BOROUGH
import uk.gov.justice.digital.hmpps.data.generator.ContactGenerator.DEFAULT_PROVIDER
import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator.OVERVIEW
import uk.gov.justice.digital.hmpps.integrations.delius.overview.entity.Contact
import uk.gov.justice.digital.hmpps.integrations.delius.overview.entity.ContactType
import uk.gov.justice.digital.hmpps.integrations.delius.overview.entity.Person
import uk.gov.justice.digital.hmpps.data.generator.UserGenerator.USER
import uk.gov.justice.digital.hmpps.data.generator.personalDetails.PersonDetailsGenerator
import uk.gov.justice.digital.hmpps.integrations.delius.overview.entity.*
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.ZoneId
import java.time.ZonedDateTime

object ContactGenerator {

val DEFAULT_PROVIDER = generateProvider("N01")
val DEFAULT_BOROUGH = generateBorough("N01B")
val DEFAULT_DISTRICT = generateDistrict("N01D")
val LOCATION_BRK_1 = generateOfficeLocation(
code = "TVP_BRK",
description = "Bracknell Office",
buildingNumber = "21",
streetName = "Some Place",
district = "District 1",
town = "Hearth",
postcode = "H34 7TH",
ldu = DEFAULT_DISTRICT
)
val DEFAULT_STAFF = generateStaff("N01BDT1", "John", "Smith")

val APPT_CT_1 = generateContactType("C089", true, "Alcohol Key Worker Session (NS)")
val OTHER_CT = generateContactType("XXXX", false, "Non attendance contact type")
val APPT_CT_2 = generateContactType("CODI", true, "Initial Appointment on Doorstep (NS)")
val APPT_CT_3 = generateContactType("CODC", true, "Planned Doorstep Contact (NS)")

val PREVIOUS_APPT_CONTACT_ABSENT = generateContact(
OVERVIEW,
APPT_CT_1,
ZonedDateTime.of(LocalDateTime.now().minusDays(1), ZoneId.of("Europe/London")),
attended = false
)
val PREVIOUS_APPT_CONTACT = generateContact(
OVERVIEW,
APPT_CT_1,
Expand All @@ -34,7 +57,24 @@ object ContactGenerator {
val NEXT_APPT_CONTACT = generateContact(
OVERVIEW,
APPT_CT_3,
ZonedDateTime.of(LocalDateTime.now().plusHours(3), ZoneId.of("Europe/London"))
ZonedDateTime.of(LocalDateTime.now().plusHours(3), ZoneId.of("Europe/London")),
linkedDocumentContactId = IdGenerator.getAndIncrement()
)

val CONTACT_DOCUMENT_1 = PersonDetailsGenerator.generateDocument(
OVERVIEW.id,
"B001",
"contact.doc",
"DOCUMENT",
primaryKeyId = NEXT_APPT_CONTACT.linkedDocumentContactId

)
val CONTACT_DOCUMENT_2 = PersonDetailsGenerator.generateDocument(
OVERVIEW.id,
"B002",
"contact2.doc",
"DOCUMENT",
primaryKeyId = NEXT_APPT_CONTACT.linkedDocumentContactId
)

fun generateContact(
Expand All @@ -44,20 +84,84 @@ object ContactGenerator {
rarActivity: Boolean? = null,
attended: Boolean? = null,
complied: Boolean? = null,
requirementId: Long? = null
sensitive: Boolean? = null,
requirement: Requirement? = null,
notes: String? = null,
linkedDocumentContactId: Long? = null
) = Contact(
IdGenerator.getAndIncrement(),
person.id,
contactType,
startDateTime.toLocalDate(),
ZonedDateTime.of(LocalDate.EPOCH, startDateTime.toLocalTime(), startDateTime.zone),
rarActivity,
attended,
complied,
requirementId
id = IdGenerator.getAndIncrement(),
personId = person.id,
type = contactType,
date = startDateTime.toLocalDate(),
startTime = ZonedDateTime.of(LocalDate.EPOCH, startDateTime.toLocalTime(), startDateTime.zone),
rarActivity = rarActivity,
attended = attended,
sensitive = sensitive,
complied = complied,
requirement = requirement,
lastUpdated = ZonedDateTime.now().minusDays(1),
lastUpdatedUser = USER,
staff = DEFAULT_STAFF,
location = LOCATION_BRK_1,
notes = notes,
linkedDocumentContactId = linkedDocumentContactId
)

private fun generateContactType(code: String, attendance: Boolean, description: String) =
ContactType(IdGenerator.getAndIncrement(), code, attendance, description)

fun generateOfficeLocation(
code: String,
description: String,
buildingName: String? = null,
buildingNumber: String? = null,
streetName: String? = null,
district: String? = null,
town: String? = null,
county: String? = null,
postcode: String? = null,
telephoneNumber: String? = null,
startDate: LocalDate = LocalDate.now(),
endDate: LocalDate? = null,
ldu: District,
id: Long = IdGenerator.getAndIncrement()
) = OfficeLocation(
code,
description,
buildingName,
buildingNumber,
streetName,
district,
town,
county,
postcode,
telephoneNumber,
startDate,
endDate,
ldu,
id
)
}

fun generateBorough(
code: String,
description: String = "Description of $code",
id: Long = IdGenerator.getAndIncrement(),
) = Borough(code, description, id)

fun generateDistrict(
code: String,
description: String = "Description of $code",
borough: Borough = DEFAULT_BOROUGH,
id: Long = IdGenerator.getAndIncrement()
) = District(code, description, borough, id)

fun generateProvider(
code: String,
description: String = "Description of $code",
id: Long = IdGenerator.getAndIncrement(),
endDate: LocalDate? = null
) = Provider(code, description, id, endDate)

fun generateStaff(code: String, forename: String, surname: String, id: Long = IdGenerator.getAndIncrement()) =
Staff(code, forename, surname, DEFAULT_PROVIDER, id)
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import uk.gov.justice.digital.hmpps.data.generator.UserGenerator.USER
import uk.gov.justice.digital.hmpps.integrations.delius.overview.entity.*
import uk.gov.justice.digital.hmpps.integrations.delius.referencedata.entity.ReferenceData
import uk.gov.justice.digital.hmpps.integrations.delius.sentence.entity.Court
import uk.gov.justice.digital.hmpps.integrations.delius.sentence.entity.CourtAppearance
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.ZoneId
Expand Down Expand Up @@ -84,7 +83,7 @@ object PersonGenerator {
LocalDate.now()
)

val MAIN_CAT_F = RequirementMainCategory(IdGenerator.getAndIncrement(), "F")
val MAIN_CAT_F = RequirementMainCategory(IdGenerator.getAndIncrement(), "F", "Main")
val REQUIREMENT = generateRequirement(ACTIVE_ORDER)
val REQUIREMENT_CONTACT_1 = ContactGenerator.generateContact(
OVERVIEW,
Expand All @@ -93,7 +92,7 @@ object PersonGenerator {
rarActivity = true,
attended = true,
complied = true,
requirementId = REQUIREMENT.id
requirement = REQUIREMENT
)
val REQUIREMENT_CONTACT_2 = ContactGenerator.generateContact(
OVERVIEW,
Expand All @@ -102,7 +101,7 @@ object PersonGenerator {
rarActivity = true,
attended = null,
complied = true,
requirementId = REQUIREMENT.id
requirement = REQUIREMENT
)

val REGISTER_TYPE_1 = generateRegisterType("CODE1", "Restraining Order")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -288,12 +288,19 @@ object PersonDetailsGenerator {
requiresInterpreter = requiresInterpreter,
)

fun generateDocument(personId: Long, alfrescoId: String, name: String, documentType: String) = PersonDocument(
fun generateDocument(
personId: Long,
alfrescoId: String,
name: String,
documentType: String,
primaryKeyId: Long? = null
) = PersonDocument(
id = IdGenerator.getAndIncrement(),
lastUpdated = ZonedDateTime.now().minusDays(1),
alfrescoId = alfrescoId,
name = name,
personId = personId,
primaryKeyId = primaryKeyId,
type = documentType
)

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

import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.Matchers.equalTo
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.result.MockMvcResultMatchers.status
import uk.gov.justice.digital.hmpps.api.model.schedule.PersonAppointment
import uk.gov.justice.digital.hmpps.api.model.schedule.Schedule
import uk.gov.justice.digital.hmpps.data.generator.ContactGenerator
import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator.OVERVIEW
import uk.gov.justice.digital.hmpps.service.toAppointment
import uk.gov.justice.digital.hmpps.service.toDocument
import uk.gov.justice.digital.hmpps.test.MockMvcExtensions.contentAsJson
import uk.gov.justice.digital.hmpps.test.MockMvcExtensions.withToken

@AutoConfigureMockMvc
@SpringBootTest(webEnvironment = RANDOM_PORT)
internal class ScheduleIntegrationTest {
@Autowired
lateinit var mockMvc: MockMvc

@Test
fun `upcoming schedule is returned`() {

val person = OVERVIEW
val res = mockMvc
.perform(get("/schedule/${person.crn}/upcoming").withToken())
.andExpect(status().isOk)
.andReturn().response.contentAsJson<Schedule>()

assertThat(res.personSummary.crn, equalTo(person.crn))
assertThat(res.appointments[0].id, equalTo(ContactGenerator.FIRST_APPT_CONTACT.toAppointment().id))
assertThat(res.appointments[0].type, equalTo(ContactGenerator.FIRST_APPT_CONTACT.toAppointment().type))
assertThat(
res.appointments[0].location?.officeName,
equalTo(ContactGenerator.FIRST_APPT_CONTACT.toAppointment().location?.officeName)
)
assertThat(res.appointments[0].location?.postcode, equalTo("H34 7TH"))
}

@Test
fun `previous schedule is returned`() {

val person = OVERVIEW
val res = mockMvc
.perform(get("/schedule/${person.crn}/previous").withToken())
.andExpect(status().isOk)
.andReturn().response.contentAsJson<Schedule>()
assertThat(res.personSummary.crn, equalTo(person.crn))
assertThat(res.appointments[0].id, equalTo(ContactGenerator.PREVIOUS_APPT_CONTACT_ABSENT.toAppointment().id))
assertThat(
res.appointments[0].type,
equalTo(ContactGenerator.PREVIOUS_APPT_CONTACT_ABSENT.toAppointment().type)
)
assertThat(
res.appointments[0].location?.officeName,
equalTo(ContactGenerator.PREVIOUS_APPT_CONTACT_ABSENT.toAppointment().location?.officeName)
)
assertThat(res.appointments[0].location?.postcode, equalTo("H34 7TH"))
}

@Test
fun `previous schedule not found status returned`() {
mockMvc
.perform(get("/schedule/X123456/previous").withToken())
.andExpect(status().isNotFound)
}

@Test
fun `Upcomimg schedule not found status returned`() {
mockMvc
.perform(get("/schedule/X123456/upcoming").withToken())
.andExpect(status().isNotFound)
}

@Test
fun `individual appointment is returned`() {

val person = OVERVIEW
val id = ContactGenerator.NEXT_APPT_CONTACT.id
val res = mockMvc
.perform(get("/schedule/${person.crn}/appointment/${id}").withToken())
.andExpect(status().isOk)
.andReturn().response.contentAsJson<PersonAppointment>()
val expectedDocs =
listOf(ContactGenerator.CONTACT_DOCUMENT_1.toDocument(), ContactGenerator.CONTACT_DOCUMENT_2.toDocument())
val expectedAppointment = ContactGenerator.NEXT_APPT_CONTACT.toAppointment().copy(documents = expectedDocs)
assertThat(res.personSummary.crn, equalTo(person.crn))
assertThat(res.appointment.id, equalTo(expectedAppointment.id))
assertThat(res.appointment.type, equalTo(expectedAppointment.type))
assertThat(res.appointment.location?.officeName, equalTo(expectedAppointment.location?.officeName))
assertThat(res.appointment.documents.size, equalTo(expectedAppointment.documents.size))
assertThat(res.appointment.location?.postcode, equalTo("H34 7TH"))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
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.ScheduleService

@RestController
@Tag(name = "Sentence")
@RequestMapping("/schedule/{crn}")
@PreAuthorize("hasRole('PROBATION_API__MANAGE_A_SUPERVISION__CASE_DETAIL')")
class ScheduleController(private val scheduleService: ScheduleService) {

@GetMapping("/upcoming")
@Operation(summary = "Gets upcoming schedule information’ ")
fun getUpcomingSchedule(@PathVariable crn: String) = scheduleService.getPersonUpcomingSchedule(crn)

@GetMapping("/previous")
@Operation(summary = "Gets previous schedule information’ ")
fun getPreviousSchedule(@PathVariable crn: String) = scheduleService.getPersonPreviousSchedule(crn)

@GetMapping("/appointment/{contactId}")
@Operation(summary = "Gets individual appointment information’ ")
fun getContact(@PathVariable crn: String, @PathVariable contactId: Long) =
scheduleService.getPersonAppointment(crn, contactId)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package uk.gov.justice.digital.hmpps.api.model.overview

data class Overview(
val appointmentsWithoutOutcome: Int = 0,
val absencesWithoutEvidence: Int = 0,
val activity: Activity?,
val compliance: Compliance?,
val personalDetails: PersonalDetails,
Expand Down
Loading

0 comments on commit b095b8f

Please sign in to comment.