Skip to content

Commit

Permalink
Man 109 schedule multiple appointments (#4381)
Browse files Browse the repository at this point in the history
* MAN-109 - update logic to add multiple appointments

* MAN-109 - update logic to add multiple appointments

* MAN-109 - when creating multiple appointments, ensure external ref is unique

* MAN-109 - add until attribute to logic

* MAN-109 - update integration test

* Formatting changes

* MAN-109 - update number of appointments calculation

* Formatting changes

* MAN-109 - removed unused import

* MAN-109 - update contact with user who has created the appointment

* Formatting changes

---------

Co-authored-by: probation-integration-bot[bot] <177347787+probation-integration-bot[bot]@users.noreply.github.com>
  • Loading branch information
1 parent f56d5ee commit 4b369fc
Show file tree
Hide file tree
Showing 11 changed files with 335 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ class DataLoader(
OffenderManagerGenerator.STAFF_USER_2,
OffenderManagerGenerator.OFFENDER_MANAGER_ACTIVE,
OffenderManagerGenerator.OFFENDER_MANAGER_INACTIVE,
OffenderManagerGenerator.DEFAULT_LOCATION,
OffenderManagerGenerator.TEAM_OFFICE,
PersonGenerator.DEFAULT_DISPOSAL_TYPE,
PersonGenerator.ACTIVE_ORDER,
LicenceConditionGenerator.LIC_COND_MAIN_CAT,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
package uk.gov.justice.digital.hmpps.data.generator

import uk.gov.justice.digital.hmpps.data.generator.ContactGenerator.DEFAULT_PROVIDER
import uk.gov.justice.digital.hmpps.integrations.delius.overview.entity.Borough
import uk.gov.justice.digital.hmpps.integrations.delius.overview.entity.District
import uk.gov.justice.digital.hmpps.integrations.delius.sentence.entity.OffenderManager
import uk.gov.justice.digital.hmpps.integrations.delius.sentence.entity.Staff
import uk.gov.justice.digital.hmpps.integrations.delius.sentence.entity.StaffUser
import uk.gov.justice.digital.hmpps.integrations.delius.sentence.entity.Team
import uk.gov.justice.digital.hmpps.integrations.delius.sentence.entity.*
import java.time.LocalDate

object OffenderManagerGenerator {

val BOROUGH = Borough("LTS_ALL", "Leicestershire All", IdGenerator.getAndIncrement())
val DISTRICT = District("LTS_ALL", "Leicestershire All", BOROUGH, IdGenerator.getAndIncrement())
val TEAM = Team(IdGenerator.getAndIncrement(), DISTRICT, "N07T02", "OMU B")
val TEAM = Team(IdGenerator.getAndIncrement(), DISTRICT, DEFAULT_PROVIDER, "N07T02", "OMU B")

val STAFF_1 = Staff(IdGenerator.getAndIncrement(), "Peter", "Parker", null)
val STAFF_2 = Staff(IdGenerator.getAndIncrement(), "Bruce", "Wayne", null)
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 DEFAULT_LOCATION = Location(IdGenerator.getAndIncrement(), "B20", "1 Birmingham Street")

val TEAM_OFFICE = TeamOfficeLink(TeamOfficeLinkId(TEAM.id, DEFAULT_LOCATION))

val OFFENDER_MANAGER_ACTIVE =
OffenderManager(
IdGenerator.getAndIncrement(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package uk.gov.justice.digital.hmpps

import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.Matchers.equalTo
import org.junit.jupiter.api.Assertions.assertNotEquals
import org.junit.jupiter.api.Test
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.MethodSource
Expand All @@ -11,15 +12,23 @@ 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.request.MockMvcRequestBuilders.post
import org.springframework.test.web.servlet.result.MockMvcResultHandlers.print
import org.springframework.test.web.servlet.result.MockMvcResultMatchers
import uk.gov.justice.digital.hmpps.api.model.appointment.AppointmentDetail
import uk.gov.justice.digital.hmpps.api.model.appointment.CreateAppointment
import uk.gov.justice.digital.hmpps.api.model.appointment.CreatedAppointment
import uk.gov.justice.digital.hmpps.api.model.appointment.User
import uk.gov.justice.digital.hmpps.data.generator.ContactGenerator.DEFAULT_PROVIDER
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
import uk.gov.justice.digital.hmpps.test.MockMvcExtensions.contentAsJson
import uk.gov.justice.digital.hmpps.test.MockMvcExtensions.withJson
import uk.gov.justice.digital.hmpps.test.MockMvcExtensions.withToken
import java.time.LocalDate
import java.time.ZonedDateTime
import java.util.*

Expand All @@ -33,6 +42,8 @@ class CreateAppointmentIntegrationTests {
@Autowired
internal lateinit var appointmentRepository: AppointmentRepository

private val user = User(STAFF_USER_1.username, TEAM.description)

@Test
fun `unauthorized status returned`() {
mockMvc
Expand All @@ -47,11 +58,13 @@ class CreateAppointmentIntegrationTests {
.withToken()
.withJson(
CreateAppointment(
user,
CreateAppointment.Type.HomeVisitToCaseNS,
ZonedDateTime.now().plusDays(1),
ZonedDateTime.now().plusDays(2),
1,
1,
interval = CreateAppointment.Interval.DAY,
numberOfAppointments = 1,
eventId = 1,
UUID.randomUUID()
)
)
Expand All @@ -65,10 +78,12 @@ class CreateAppointmentIntegrationTests {
.withToken()
.withJson(
CreateAppointment(
user,
CreateAppointment.Type.InitialAppointmentInOfficeNS,
ZonedDateTime.now().plusDays(2),
ZonedDateTime.now().plusDays(1),
1,
interval = CreateAppointment.Interval.DAY,
numberOfAppointments = 1,
PersonGenerator.EVENT_1.id,
UUID.randomUUID()
)
Expand All @@ -87,37 +102,110 @@ class CreateAppointmentIntegrationTests {
.withJson(createAppointment)
)
.andExpect(MockMvcResultMatchers.status().isCreated)
.andReturn().response.contentAsJson<CreatedAppointment>()
.andReturn().response.contentAsJson<AppointmentDetail>()

val appointment = appointmentRepository.findById(response.id).get()
val appointment = appointmentRepository.findById(response.appointments[0].id).get()

assertThat(appointment.type.code, equalTo(createAppointment.type.code))
assertThat(appointment.date, equalTo(createAppointment.start.toLocalDate()))
assertThat(appointment.startTime, isCloseTo(createAppointment.start))
assertThat(appointment.externalReference, equalTo(createAppointment.urn))
assertThat(appointment.eventId, equalTo(createAppointment.eventId))
assertThat(appointment.createdByUserId, equalTo(STAFF_USER_1.id))
assertThat(appointment.staffId, equalTo(STAFF_1.id))
assertThat(appointment.probationAreaId, equalTo(DEFAULT_PROVIDER.id))
assertThat(appointment.officeLocationId, equalTo(DEFAULT_LOCATION.id))


appointmentRepository.delete(appointment)
}

@ParameterizedTest
@MethodSource("createMultipleAppointments")
fun `create multiple appointments`(createAppointment: CreateAppointment) {
val person = PersonGenerator.PERSON_1
val response = mockMvc.perform(
post("/appointments/${person.crn}")
.withToken()
.withJson(createAppointment)
)
.andDo(print())
.andExpect(MockMvcResultMatchers.status().isCreated)
.andReturn().response.contentAsJson<AppointmentDetail>()

val appointments = appointmentRepository.findAllById(response.appointments.map { it.id })

assertThat(appointments.size, equalTo(3))

assertThat(appointments[0].date, equalTo(LocalDate.now()))
assertThat(
appointments[1].date,
equalTo(LocalDate.now().plusDays(createAppointment.interval.value.toLong() * 1))
)
assertThat(
appointments[2].date,
equalTo(LocalDate.now().plusDays(createAppointment.interval.value.toLong() * 2))
)

//check for unique external reference
val externalRef = "urn:uk:gov:hmpps:manage-supervision-service:appointment:${createAppointment.uuid}"
assertThat(appointments[0].externalReference, equalTo(externalRef))
assertNotEquals(externalRef, appointments[1].externalReference)
assertNotEquals(externalRef, appointments[2].externalReference)

appointmentRepository.deleteAll(appointments)
}

companion object {
private val user = User(STAFF_USER_1.username, TEAM.description)

@JvmStatic
fun createAppointments() = listOf(
CreateAppointment(
user,
CreateAppointment.Type.PlannedOfficeVisitNS,
ZonedDateTime.now().plusDays(1),
ZonedDateTime.now().plusDays(2),
1,
PersonGenerator.EVENT_1.id,
UUID.randomUUID()
eventId = PersonGenerator.EVENT_1.id,
uuid = UUID.randomUUID()
),
CreateAppointment(
user,
CreateAppointment.Type.InitialAppointmentInOfficeNS,
ZonedDateTime.now().plusDays(1),
null,
1,
PersonGenerator.EVENT_1.id,
UUID.randomUUID()
CreateAppointment.Interval.DAY,
eventId = PersonGenerator.EVENT_1.id,
uuid = UUID.randomUUID()
)
)

@JvmStatic
fun createMultipleAppointments() = listOf(
CreateAppointment(
user,
CreateAppointment.Type.HomeVisitToCaseNS,
ZonedDateTime.now(),
numberOfAppointments = 3,
eventId = PersonGenerator.EVENT_1.id,
uuid = UUID.randomUUID()
),
CreateAppointment(
user,
CreateAppointment.Type.HomeVisitToCaseNS,
ZonedDateTime.now(),
until = ZonedDateTime.now().plusDays(3),
eventId = PersonGenerator.EVENT_1.id,
uuid = UUID.randomUUID()
),
CreateAppointment(
user,
CreateAppointment.Type.HomeVisitToCaseNS,
start = ZonedDateTime.now(),
until = ZonedDateTime.now().plusDays(21),
interval = CreateAppointment.Interval.WEEK,
eventId = PersonGenerator.EVENT_1.id,
uuid = UUID.randomUUID()
)
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import org.springframework.http.HttpStatus
import org.springframework.security.access.prepost.PreAuthorize
import org.springframework.web.bind.annotation.*
import uk.gov.justice.digital.hmpps.api.model.appointment.CreateAppointment
import uk.gov.justice.digital.hmpps.service.AppointmentService
import uk.gov.justice.digital.hmpps.service.SentenceAppointmentService

@RestController
@Tag(name = "Sentence")
@RequestMapping("/appointments/{crn}")
@PreAuthorize("hasRole('PROBATION_API__MANAGE_A_SUPERVISION__CASE_DETAIL')")
class AppointmentController(private val appointmentService: AppointmentService) {
class AppointmentController(private val appointmentService: SentenceAppointmentService) {

@PostMapping
@ResponseStatus(HttpStatus.CREATED)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package uk.gov.justice.digital.hmpps.api.model.appointment

data class AppointmentDetail(
val appointments: List<CreatedAppointment>,
)

data class CreatedAppointment(
val id: Long
)
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@ import java.time.ZonedDateTime
import java.util.*

data class CreateAppointment(
val user: User,
val type: Type,
val start: ZonedDateTime,
val end: ZonedDateTime?,
val interval: Int,
val end: ZonedDateTime? = null,
val interval: Interval = Interval.DAY,
val numberOfAppointments: Int = 1,
val eventId: Long,
val uuid: UUID,
val requirementId: Long? = null,
val licenceConditionId: Long? = null,
val numberOfAppointments: Int? = null,
val until: ZonedDateTime? = null
) {
@JsonIgnore
Expand All @@ -26,7 +27,19 @@ data class CreateAppointment(
InitialAppointmentHomeVisitNS("COHV")
}

enum class Interval(val value: Int) {
DAY(1),
WEEK(7),
FORTNIGHT(14),
FOUR_WEEKS(28)
}

companion object {
const val URN_PREFIX = "urn:uk:gov:hmpps:manage-supervision-service:appointment:"
}
}

data class User(
val username: String,
val team: String
)
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,7 @@ class Contact(
@Column(name = "soft_deleted", columnDefinition = "NUMBER", nullable = false)
val softDeleted: Boolean = false,

val partitionAreaId: Long = 0,

val createdByUserId: Long = 0
val partitionAreaId: Long = 0
) {

fun startDateTime(): ZonedDateTime =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package uk.gov.justice.digital.hmpps.integrations.delius.sentence.entity

import jakarta.persistence.*
import org.hibernate.annotations.SQLRestriction
import org.springframework.data.annotation.CreatedBy
import org.springframework.data.annotation.CreatedDate
import org.springframework.data.annotation.LastModifiedBy
import org.springframework.data.annotation.LastModifiedDate
Expand Down Expand Up @@ -37,13 +36,11 @@ class Appointment(
@Column(name = "contact_start_time")
val startTime: ZonedDateTime,

@ManyToOne
@JoinColumn(name = "team_id")
val team: Team,
@Column(name = "team_id")
val teamId: Long,

@ManyToOne
@JoinColumn(name = "staff_id")
val staff: Staff,
@Column(name = "staff_id")
val staffId: Long,

@Column(name = "last_updated_user_id")
@LastModifiedBy
Expand Down Expand Up @@ -74,16 +71,19 @@ class Appointment(
@Column(name = "row_version")
val version: Long = 0,

@Column(name = "created_by_user_id")
val createdByUserId: Long? = null,

@Column(name = "office_location_id")
val officeLocationId: Long? = null,

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "contact_id_generator")
@Column(name = "contact_id")
val id: Long = 0
) {
var partitionAreaId: Long = 0

@CreatedBy
var createdByUserId: Long = 0

@CreatedDate
@Column(name = "created_datetime")
var createdDateTime: ZonedDateTime = ZonedDateTime.now()
Expand Down
Loading

0 comments on commit 4b369fc

Please sign in to comment.