Skip to content

Commit

Permalink
Man 28 sentence license condition notes (#4321)
Browse files Browse the repository at this point in the history
* MAN-28 - add licence condition information to api

* MAN-28 - update model from nullable list to non nullable list

* MAN-28 - update model so that notes are sent as a list

* Formatting changes

* MAN-28 - process note without 'Comment added by...'

* Formatting changes

* MAN-28 - process note without 'Comment added by...'

* MAN-28 - update LicenceConditionNote.createdBy

* MAN-28 - add new attribute to response

* Formatting changes

* MAN-28 - limit licence note to 1500 characters

* MAN-28 - limit licence note to 1500 characters

* MAN-28 - remove characters not needed

* MAN-28 - apply review comments

---------

Co-authored-by: probation-integration-bot[bot] <177347787+probation-integration-bot[bot]@users.noreply.github.com>
  • Loading branch information
1 parent 6cff799 commit 35dce3c
Show file tree
Hide file tree
Showing 8 changed files with 253 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@ class DataLoader(
OffenderManagerGenerator.OFFENDER_MANAGER_INACTIVE,
PersonGenerator.DEFAULT_DISPOSAL_TYPE,
PersonGenerator.ACTIVE_ORDER,
LicenceConditionGenerator.LIC_COND_MAIN_CAT,
LicenceConditionGenerator.LIC_COND_SUB_CAT,
LicenceConditionGenerator.LC_WITH_NOTES,
LicenceConditionGenerator.LC_WITHOUT_NOTES,
LicenceConditionGenerator.LC_WITH_NOTES_WITHOUT_ADDED_BY,
PersonGenerator.TERMINATION_REASON,
PersonGenerator.REF_DATA_YEARS,
PersonGenerator.INACTIVE_ORDER_1,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package uk.gov.justice.digital.hmpps.data.generator

import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator.ACTIVE_ORDER
import uk.gov.justice.digital.hmpps.integrations.delius.referencedata.entity.ReferenceData
import uk.gov.justice.digital.hmpps.integrations.delius.sentence.entity.LicenceCondition
import uk.gov.justice.digital.hmpps.integrations.delius.sentence.entity.LicenceConditionMainCategory
import java.time.LocalDate

object LicenceConditionGenerator {

val LIC_COND_MAIN_CAT = LicenceConditionMainCategory(
IdGenerator.getAndIncrement(),
"LicMain",
"lic cond main"
)

val LIC_COND_SUB_CAT = ReferenceData(
IdGenerator.getAndIncrement(),
"LicSub",
"Lic Sub cat"
)

val LC_WITHOUT_NOTES = LicenceCondition(
IdGenerator.getAndIncrement(),
LIC_COND_MAIN_CAT,
null,
ACTIVE_ORDER.id,
LocalDate.now().minusDays(14),
null,
null
)

val LC_WITH_NOTES = LicenceCondition(
IdGenerator.getAndIncrement(),
LIC_COND_MAIN_CAT,
LIC_COND_SUB_CAT,
ACTIVE_ORDER.id,
LocalDate.now().minusDays(7),
LocalDate.now(),
"""
Comment added by CVL Service on 22/04/2024 at 10:00
Licence Condition created automatically from the Create and Vary a licence system of\nAllow person(s) as designated by your supervising officer to install an electronic monitoring tag on you and access to install any associated equipment in your property, and for the purpose of ensuring that equipment is functioning correctly. You must not damage or tamper with these devices and ensure that the tag is charged, and report to your supervising officer and the EM provider immediately if the tag or the associated equipment are not working correctly. This will be for the purpose of monitoring your alcohol abstinence licence condition(s) unless otherwise authorised by your supervising officer. Licence Condition created automatically from the Create and Vary a licence system of\nAllow person(s) as designated by your supervising officer to install an electronic monitoring tag on you and access to install any associated equipment in your property, and for the purpose of ensuring that equipment is functioning correctly. You must not damage or tamper with these devices and ensure that the tag is charged, and report to your supervising officer and the EM provider immediately if the tag or the associated equipment are not working correctly. This will be for the purpose of monitoring your alcohol abstinence licence condition(s) unless otherwise authorised by your supervising officer.Licence Condition created automatically from the Create and Vary a licence system of\nAllow person(s) as desi123456
---------------------------------------------------------
Comment added by Joe Root on 23/04/2024 at 13:45
You must not drink any alcohol until Wednesday 7th August 2024 unless your
probation officer says you can. You will need to wear an electronic tag all the time so
we can check this.
""".trimIndent()
)

val LC_WITH_NOTES_WITHOUT_ADDED_BY = LicenceCondition(
IdGenerator.getAndIncrement(),
LIC_COND_MAIN_CAT,
LIC_COND_SUB_CAT,
ACTIVE_ORDER.id,
LocalDate.now().minusDays(7),
LocalDate.now(),
"""
He shall not contact or associate with Peter Jones without the prior approval of the supervising officer;
""".trimIndent()
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import uk.gov.justice.digital.hmpps.service.toSummary
import uk.gov.justice.digital.hmpps.test.MockMvcExtensions.contentAsJson
import uk.gov.justice.digital.hmpps.test.MockMvcExtensions.withToken
import java.time.LocalDate
import uk.gov.justice.digital.hmpps.data.generator.LicenceConditionGenerator.LIC_COND_MAIN_CAT
import uk.gov.justice.digital.hmpps.data.generator.LicenceConditionGenerator.LIC_COND_SUB_CAT

@AutoConfigureMockMvc
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
Expand Down Expand Up @@ -62,7 +64,8 @@ class SentenceIntegrationTest {
null,
listOf(),
listOf(),
null
null,
listOf()
),
Sentence(
OffenceDetails(
Expand Down Expand Up @@ -114,7 +117,51 @@ class SentenceIntegrationTest {
CourtDocument(COURT_DOCUMENT.alfrescoId, LocalDate.now().minusDays(1), "court report"),
CourtDocument(EVENT_DOCUMENT.alfrescoId, LocalDate.now().minusDays(3), "event report")
),
"3 minutes completed (of 12 hours)"
"3 minutes completed (of 12 hours)",
listOf(
LicenceCondition(
LIC_COND_MAIN_CAT.description,
LIC_COND_SUB_CAT.description,
LocalDate.now().minusDays(7),
LocalDate.now(),
listOf(
LicenceConditionNote(
"CVL Service",
LocalDate.of(2024, 4, 22),
"""
Licence Condition created automatically from the Create and Vary a licence system of\nAllow person(s) as designated by your supervising officer to install an electronic monitoring tag on you and access to install any associated equipment in your property, and for the purpose of ensuring that equipment is functioning correctly. You must not damage or tamper with these devices and ensure that the tag is charged, and report to your supervising officer and the EM provider immediately if the tag or the associated equipment are not working correctly. This will be for the purpose of monitoring your alcohol abstinence licence condition(s) unless otherwise authorised by your supervising officer. Licence Condition created automatically from the Create and Vary a licence system of\nAllow person(s) as designated by your supervising officer to install an electronic monitoring tag on you and access to install any associated equipment in your property, and for the purpose of ensuring that equipment is functioning correctly. You must not damage or tamper with these devices and ensure that the tag is charged, and report to your supervising officer and the EM provider immediately if the tag or the associated equipment are not working correctly. This will be for the purpose of monitoring your alcohol abstinence licence condition(s) unless otherwise authorised by your supervising officer.Licence Condition created automatically from the Create and Vary a licence system of\nAllow person(s) as desi
""".trimIndent(),
true
),
LicenceConditionNote(
"Joe Root",
LocalDate.of(2024, 4, 23),
"""
You must not drink any alcohol until Wednesday 7th August 2024 unless your
probation officer says you can. You will need to wear an electronic tag all the time so
we can check this.
""".trimIndent(),
false
),
)
),
LicenceCondition(
LIC_COND_MAIN_CAT.description,
imposedReleasedDate = LocalDate.now().minusDays(14),
),
LicenceCondition(
LIC_COND_MAIN_CAT.description,
LIC_COND_SUB_CAT.description,
LocalDate.now().minusDays(7),
LocalDate.now(),
listOf(
LicenceConditionNote(
note = "He shall not contact or associate with Peter Jones without the prior approval of the supervising officer;",
hasNotesBeenTruncated = false
)
)
)
)
)
),
ProbationHistory(2, LocalDate.now().minusDays(7), 2, 2)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package uk.gov.justice.digital.hmpps.api.model.sentence

import java.time.LocalDate

data class LicenceCondition(
val mainDescription: String,
val subTypeDescription: String? = null,
val imposedReleasedDate: LocalDate,
val actualStartDate: LocalDate? = null,
val notes: List<LicenceConditionNote> = listOf()
)

data class LicenceConditionNote(
val createdBy: String? = null,
val createdByDate: LocalDate? = null,
val note: String,
val hasNotesBeenTruncated: Boolean? = null
)
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ data class Sentence(
val order: Order? = null,
val requirements: List<Requirement> = listOf(),
val courtDocuments: List<CourtDocument> = listOf(),
val unpaidWorkProgress: String?
val unpaidWorkProgress: String?,
val licenceConditions: List<LicenceCondition> = listOf()
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package uk.gov.justice.digital.hmpps.integrations.delius.sentence.entity

import jakarta.persistence.*
import org.hibernate.annotations.Immutable
import org.hibernate.annotations.SQLRestriction
import org.springframework.data.jpa.repository.JpaRepository
import uk.gov.justice.digital.hmpps.integrations.delius.referencedata.entity.ReferenceData
import java.time.LocalDate

@Immutable
@Entity
@Table(name = "lic_condition")
@SQLRestriction("soft_deleted = 0 and active_flag = 1")
class LicenceCondition(
@Id
@Column(name = "lic_condition_id", nullable = false)
val id: Long,

@ManyToOne
@JoinColumn(name = "lic_cond_type_main_cat_id")
val mainCategory: LicenceConditionMainCategory,

@ManyToOne
@JoinColumn(name = "lic_cond_type_sub_cat_id")
val subCategory: ReferenceData?,

@Column
val disposalId: Long,

@Column(name = "start_date", nullable = false)
val imposedReleasedDate: LocalDate,

@Column(name = "commencement_date")
val actualStartDate: LocalDate?,

@Column(name = "lic_condition_notes", columnDefinition = "clob")
val notes: String?,

@Column(name = "active_flag", columnDefinition = "number", nullable = false)
val active: Boolean = true,

@Column(columnDefinition = "number")
val softDeleted: Boolean = false
)

interface LicenceConditionRepository : JpaRepository<LicenceCondition, Long> {
fun findAllByDisposalId(disposalId: Long): List<LicenceCondition>
}

@Immutable
@Table(name = "r_lic_cond_type_main_cat")
@Entity
class LicenceConditionMainCategory(
@Id
@Column(name = "lic_cond_type_main_cat_id")
val id: Long,

@Column
val code: String,

@Column
val description: String
)
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import uk.gov.justice.digital.hmpps.api.model.overview.Rar
import uk.gov.justice.digital.hmpps.api.model.sentence.*
import uk.gov.justice.digital.hmpps.api.model.sentence.Offence
import uk.gov.justice.digital.hmpps.api.model.sentence.Requirement
import uk.gov.justice.digital.hmpps.datetime.DeliusDateFormatter
import uk.gov.justice.digital.hmpps.integrations.delius.overview.entity.*
import uk.gov.justice.digital.hmpps.integrations.delius.personalDetails.entity.CourtDocumentDetails
import uk.gov.justice.digital.hmpps.integrations.delius.personalDetails.entity.DocumentRepository
Expand All @@ -14,6 +15,7 @@ import java.time.Duration
import java.time.LocalDate
import kotlin.time.toKotlinDuration
import uk.gov.justice.digital.hmpps.integrations.delius.sentence.entity.AdditionalSentence as ExtraSentence
import uk.gov.justice.digital.hmpps.integrations.delius.sentence.entity.LicenceCondition as EntityLicenceCondition

@Service
class SentenceService(
Expand All @@ -24,7 +26,8 @@ class SentenceService(
private val requirementRepository: RequirementRepository,
private val documentRepository: DocumentRepository,
private val offenderManagerRepository: OffenderManagerRepository,
private val upwAppointmentRepository: UpwAppointmentRepository
private val upwAppointmentRepository: UpwAppointmentRepository,
private val licenceConditionRepository: LicenceConditionRepository
) {
fun getEvents(crn: String): SentenceOverview {
val person = personRepository.getPerson(crn)
Expand Down Expand Up @@ -67,9 +70,53 @@ class SentenceService(
requirements = requirementRepository.getRequirements(id, eventNumber)
.map { it.toRequirement() },
courtDocuments = documentRepository.getCourtDocuments(id, eventNumber).map { it.toCourtDocument() },
disposal?.id?.let { getUnpaidWorkTime(it) }
disposal?.id?.let { getUnpaidWorkTime(it) },
licenceConditions = disposal?.let {
licenceConditionRepository.findAllByDisposalId(disposal.id).map {
it.toLicenceCondition()
}
} ?: emptyList(),
)

fun EntityLicenceCondition.toLicenceCondition() =
LicenceCondition(
mainCategory.description,
subCategory?.description,
imposedReleasedDate,
actualStartDate,
populateLicenceConditionNotes(notes)
)

fun populateLicenceConditionNotes(notes: String?): List<LicenceConditionNote> {
val noteLength = 1500

notes?.let {
val splitParam = "---------------------------------------------------------" + System.lineSeparator()
return notes.split(splitParam).map { note ->
val matchResult = Regex(
"^Comment added by (.+?) on (\\d{2}/\\d{2}/\\d{4}) at \\d{2}:\\d{2}"
+ System.lineSeparator()
).find(note)
val commentLine = matchResult?.value
val commentText = commentLine?.let { note.removePrefix(commentLine) } ?: note

val userCreatedBy = matchResult?.groupValues?.get(1)
val dateCreatedBy = matchResult?.groupValues?.get(2)
?.let { LocalDate.parse(it, DeliusDateFormatter) }


LicenceConditionNote(
userCreatedBy,
dateCreatedBy,
commentText.removeSuffix(System.lineSeparator()).chunked(1500)[0],
note.length > noteLength
)
}

}
return listOf()
}

fun ExtraSentence.toAdditionalSentence(): AdditionalSentence =
AdditionalSentence(length, amount, notes, type.description)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ class SentenceServiceTest {
@Mock
lateinit var upwAppointmentRepository: UpwAppointmentRepository

@Mock
lateinit var licenceConditionRepository: LicenceConditionRepository

@InjectMocks
lateinit var service: SentenceService

Expand Down Expand Up @@ -263,7 +266,8 @@ class SentenceServiceTest {
)
),
listOf(CourtDocument("A001", LocalDate.now(), "Pre Sentence Event")),
"65 hours 36 minutes completed (of 70 hours)"
"65 hours 36 minutes completed (of 70 hours)",
listOf()
)
),
ProbationHistory(0, null, 0, 0)
Expand Down

0 comments on commit 35dce3c

Please sign in to comment.