Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PI-1991: Added schedule endpoints #3520

Merged
merged 4 commits into from
Mar 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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