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

Man 28 sentence license condition notes #4321

Merged
merged 19 commits into from
Oct 17, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
736f3d0
MAN-28 - add licence condition information to api
achimber-moj Oct 10, 2024
090707a
MAN-28 - update model from nullable list to non nullable list
achimber-moj Oct 10, 2024
bc9ae95
MAN-28 - update model so that notes are sent as a list
achimber-moj Oct 16, 2024
50acf6c
Formatting changes
probation-integration-bot[bot] Oct 16, 2024
05089f1
Merge branch 'main' into MAN-28-sentence-license-condition-notes
achimber-moj Oct 16, 2024
65cfc52
MAN-28 - process note without 'Comment added by...'
achimber-moj Oct 16, 2024
81c2bb6
Formatting changes
probation-integration-bot[bot] Oct 16, 2024
8ef3d6c
MAN-28 - process note without 'Comment added by...'
achimber-moj Oct 16, 2024
b1106e9
Merge remote-tracking branch 'origin/MAN-28-sentence-license-conditio…
achimber-moj Oct 16, 2024
25840f4
MAN-28 - update LicenceConditionNote.createdBy
achimber-moj Oct 16, 2024
9a2f401
MAN-28 - add new attribute to response
achimber-moj Oct 16, 2024
ae59bf2
Formatting changes
probation-integration-bot[bot] Oct 16, 2024
c2c43fe
MAN-28 - limit licence note to 1500 characters
achimber-moj Oct 16, 2024
d08f583
Merge remote-tracking branch 'origin/MAN-28-sentence-license-conditio…
achimber-moj Oct 16, 2024
8c81d51
MAN-28 - limit licence note to 1500 characters
achimber-moj Oct 16, 2024
69df04b
MAN-28 - remove characters not needed
achimber-moj Oct 16, 2024
c4abf5f
Merge branch 'main' into MAN-28-sentence-license-condition-notes
achimber-moj Oct 17, 2024
21ac1a5
MAN-28 - apply review comments
achimber-moj Oct 17, 2024
ef8d77e
Merge remote-tracking branch 'origin/MAN-28-sentence-license-conditio…
achimber-moj Oct 17, 2024
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 @@ -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(
"Comment added by 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(
"Comment added by 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 @@ -10,8 +10,10 @@ 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
import uk.gov.justice.digital.hmpps.integrations.delius.sentence.entity.*
import uk.gov.justice.digital.hmpps.integrations.delius.sentence.entity.LicenceCondition as EntityLicenceCondition
import java.time.Duration
import java.time.LocalDate
import java.time.format.DateTimeFormatter
import kotlin.time.toKotlinDuration
import uk.gov.justice.digital.hmpps.integrations.delius.sentence.entity.AdditionalSentence as ExtraSentence

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,65 @@ 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 addedBy = Regex(
"^Comment added by .+? on \\d{2}/\\d{2}/\\d{4} at \\d{2}:\\d{2}"
+ System.lineSeparator()
).find(note)?.value
val noteText = addedBy?.let { note.removePrefix(addedBy) } ?: note

val createdBy = addedBy?.removeSuffix(System.lineSeparator())?.reversed()?.substring(23)?.reversed()
val dateCreatedBy =
addedBy?.removeSuffix(System.lineSeparator())?.reversed()?.substring(9, 19)?.reversed()
achimber-moj marked this conversation as resolved.
Show resolved Hide resolved

LicenceConditionNote(
createdBy,
dateCreatedBy?.let { LocalDate.parse(it, DateTimeFormatter.ofPattern("d/MM/yyyy")) },
noteText.removeSuffix(System.lineSeparator()).chunked(1500)[0],
note.let { n ->
when {
n.length > noteLength -> true
else -> false
}
}
)
}

}
return listOf()
}

fun hasNotesBeenTruncated(notes: String): Boolean? {
return notes.let {
when {
it.length > 1500 -> true
else -> false
}
}
}

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
Loading