Skip to content

Commit

Permalink
Man 109 backend create appointment in mms (#4365)
Browse files Browse the repository at this point in the history
* MAN-109 - add new api

* MAN-109 - update audit params

* MAN-109 - add integration test

* MAN-109 - add integration test

* MAN-109 - update integration test

* MAN-109 - refactor db layer and update tests

* MAN-109 - add error logic

* MAN-109 - add error logic

* MAN-109 - update data saved to db and add service test

* MAN-109 - update data saved to db and add service test

* MAN-109 - update db object

* MAN-109 - remove duplicated code

* MAN-109 - make CreateAppointment.end as a optional parameter

* MAN-109 - update integration test

* MAN-109 - add return object

* MAN-109 - update integration test

* MAN-109 - delete repo class not needed

* MAN-109 - undo delete of repo class not, due to ci build failure

* MAN-109 - delete of repo class not required

* MAN-109 - comment out code temporarily, due to ci failure

* MAN-109 - fix deployment error

* MAN-109 - update service and tests

* MAN-109 - update database access file

* MAN-109 - update database access file to remove sequence section.

* Formatting changes

* MAN-109 - set mandatory db columns

* MAN-109 - apply review comments

* MAN-109 - comment added

* MAN-109 - do not set a default value to uuid

---------

Co-authored-by: probation-integration-bot[bot] <177347787+probation-integration-bot[bot]@users.noreply.github.com>
  • Loading branch information
1 parent 434a481 commit b2a4fb3
Show file tree
Hide file tree
Showing 16 changed files with 684 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ database:
access:
username_key: /manage-supervision-and-delius/db-username
password_key: /manage-supervision-and-delius/db-password
tables:
- contact

audit:
username: ManageSupervisionAndDelius
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@ import org.springframework.boot.context.event.ApplicationReadyEvent
import org.springframework.context.ApplicationListener
import org.springframework.stereotype.Component
import org.springframework.transaction.annotation.Transactional
import uk.gov.justice.digital.hmpps.audit.BusinessInteraction
import uk.gov.justice.digital.hmpps.data.generator.*
import uk.gov.justice.digital.hmpps.data.generator.CourtAppearanceGenerator.COURT_APPEARANCE
import uk.gov.justice.digital.hmpps.data.generator.personalDetails.PersonDetailsGenerator
import uk.gov.justice.digital.hmpps.integrations.delius.audit.BusinessInteractionCode
import uk.gov.justice.digital.hmpps.user.AuditUserRepository
import java.time.ZonedDateTime

@Component
@ConditionalOnProperty("seed.database")
Expand All @@ -27,7 +30,11 @@ class DataLoader(
@Transactional
override fun onApplicationEvent(are: ApplicationReadyEvent) {

BusinessInteractionCode.entries.forEach {
entityManager.persist(BusinessInteraction(IdGenerator.getAndIncrement(), it.code, ZonedDateTime.now()))
}
entityManager.persistAll(
*AppointmentGenerator.APPOINTMENT_TYPES.toTypedArray(),
ContactGenerator.DEFAULT_PROVIDER,
ContactGenerator.DEFAULT_BOROUGH,
ContactGenerator.DEFAULT_DISTRICT,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package uk.gov.justice.digital.hmpps.data.generator

import uk.gov.justice.digital.hmpps.api.model.appointment.CreateAppointment
import uk.gov.justice.digital.hmpps.integrations.delius.overview.entity.ContactType

object AppointmentGenerator {

val APPOINTMENT_TYPES = CreateAppointment.Type.entries.map { generateType(it.code, attendanceType = true) }

fun generateType(
code: String,
description: String = "Description for $code",
attendanceType: Boolean,
id: Long = IdGenerator.getAndIncrement()
) = ContactType(IdGenerator.getAndIncrement(), code, true, description)
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ object OffenderManagerGenerator {
ContactGenerator.DEFAULT_PROVIDER,
TEAM,
STAFF_2,
LocalDate.now()
LocalDate.now(),
active = false
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package uk.gov.justice.digital.hmpps

import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.Matchers.equalTo
import org.junit.jupiter.api.Test
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.MethodSource
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.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.MockMvcResultMatchers
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.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.ZonedDateTime
import java.util.*

@AutoConfigureMockMvc
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class CreateAppointmentIntegrationTests {

@Autowired
internal lateinit var mockMvc: MockMvc

@Autowired
internal lateinit var appointmentRepository: AppointmentRepository

@Test
fun `unauthorized status returned`() {
mockMvc
.perform(MockMvcRequestBuilders.get("/appointments/D123456"))
.andExpect(MockMvcResultMatchers.status().isUnauthorized)
}

@Test
fun `when offender does not exist retuns a 404 response`() {
mockMvc.perform(
post("/appointments/D123456")
.withToken()
.withJson(
CreateAppointment(
CreateAppointment.Type.HomeVisitToCaseNS,
ZonedDateTime.now().plusDays(1),
ZonedDateTime.now().plusDays(2),
1,
1,
UUID.randomUUID()
)
)
).andExpect(MockMvcResultMatchers.status().isNotFound)
}

@Test
fun `appointment end date before start returns bad request`() {
mockMvc.perform(
post("/appointments/${PersonGenerator.PERSON_1.crn}")
.withToken()
.withJson(
CreateAppointment(
CreateAppointment.Type.InitialAppointmentInOfficeNS,
ZonedDateTime.now().plusDays(2),
ZonedDateTime.now().plusDays(1),
1,
PersonGenerator.EVENT_1.id,
UUID.randomUUID()
)
)
).andExpect(MockMvcResultMatchers.status().isBadRequest)
}

@ParameterizedTest
@MethodSource("createAppointments")
fun `create a new appointment`(createAppointment: CreateAppointment) {
val person = PersonGenerator.PERSON_1

val response = mockMvc.perform(
post("/appointments/${person.crn}")
.withToken()
.withJson(createAppointment)
)
.andExpect(MockMvcResultMatchers.status().isCreated)
.andReturn().response.contentAsJson<CreatedAppointment>()

val appointment = appointmentRepository.findById(response.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))

appointmentRepository.delete(appointment)
}

companion object {
@JvmStatic
fun createAppointments() = listOf(
CreateAppointment(
CreateAppointment.Type.PlannedOfficeVisitNS,
ZonedDateTime.now().plusDays(1),
ZonedDateTime.now().plusDays(2),
1,
PersonGenerator.EVENT_1.id,
UUID.randomUUID()
),
CreateAppointment(
CreateAppointment.Type.InitialAppointmentInOfficeNS,
ZonedDateTime.now().plusDays(1),
null,
1,
PersonGenerator.EVENT_1.id,
UUID.randomUUID()
)
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package uk.gov.justice.digital.hmpps.api.controller

import io.swagger.v3.oas.annotations.tags.Tag
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

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

@PostMapping
@ResponseStatus(HttpStatus.CREATED)
fun createAppointment(@PathVariable crn: String, @RequestBody createAppointment: CreateAppointment) =
appointmentService.createAppointment(crn, createAppointment)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package uk.gov.justice.digital.hmpps.api.model.appointment

import com.fasterxml.jackson.annotation.JsonIgnore
import java.time.ZonedDateTime
import java.util.*

data class CreateAppointment(
val type: Type,
val start: ZonedDateTime,
val end: ZonedDateTime?,
val interval: Int,
val eventId: Long,
val uuid: UUID,
val requirementId: Long? = null,
val licenceConditionId: Long? = null,
val numberOfAppointments: Int? = null,
val until: ZonedDateTime? = null
) {
@JsonIgnore
val urn = URN_PREFIX + uuid

enum class Type(val code: String) {
HomeVisitToCaseNS("CHVS"),
InitialAppointmentInOfficeNS("COAI"),
PlannedOfficeVisitNS("COAP"),
InitialAppointmentHomeVisitNS("COHV")
}

companion object {
const val URN_PREFIX = "urn:uk:gov:hmpps:manage-supervision-service:appointment:"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package uk.gov.justice.digital.hmpps.api.model.appointment

data class CreatedAppointment(
val id: Long
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package uk.gov.justice.digital.hmpps.integrations.delius.audit

import uk.gov.justice.digital.hmpps.audit.InteractionCode

enum class BusinessInteractionCode(override val code: String) : InteractionCode {
ADD_CONTACT("CLBI003")
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,13 @@ class Contact(
val lastUpdatedUser: User,

@Column(name = "soft_deleted", columnDefinition = "NUMBER", nullable = false)
val softDeleted: Boolean = false
val softDeleted: Boolean = false,

val partitionAreaId: Long = 0,

val createdByUserId: Long = 0
) {

fun startDateTime(): ZonedDateTime =
if (startTime != null) ZonedDateTime.of(date, startTime.toLocalTime(), EuropeLondon) else
ZonedDateTime.of(date, date.atStartOfDay().toLocalTime(), EuropeLondon)
Expand Down
Loading

0 comments on commit b2a4fb3

Please sign in to comment.