Skip to content

Commit

Permalink
Feature/pi 2158 mas get unpaid work time (#3741)
Browse files Browse the repository at this point in the history
* PI-2158 return unpaid time worked

Signed-off-by: Amardeep Chimber <[email protected]>

* PI-2158 update integration layer

Signed-off-by: Amardeep Chimber <[email protected]>

* PI-2158 update service

Signed-off-by: Amardeep Chimber <[email protected]>

* PI-2158 update tests

Signed-off-by: Amardeep Chimber <[email protected]>

* PI-2158 update integration test and dataloader

Signed-off-by: Amardeep Chimber <[email protected]>

* PI-2158 update service test

Signed-off-by: Amardeep Chimber <[email protected]>

* PI-2158 change minutes to hour calculation

Signed-off-by: Amardeep Chimber <[email protected]>

* PI-2158 amend logic

Signed-off-by: Amardeep Chimber <[email protected]>

* PI-2158 apply review comments to amend sql

Signed-off-by: Amardeep Chimber <[email protected]>

* Formatting changes

* PI-2158 convert query from native to jpql

Signed-off-by: Amardeep Chimber <[email protected]>

* PI-2158 remove commented code

Signed-off-by: Amardeep Chimber <[email protected]>

* PI-2158 add more service test to cover unpaid work progress

Signed-off-by: Amardeep Chimber <[email protected]>

* Formatting changes

* PI-2158 update service logic

Signed-off-by: Amardeep Chimber <[email protected]>

* PI-2158 update service logic

Signed-off-by: Amardeep Chimber <[email protected]>

* PI-2158 update service logic

Signed-off-by: Amardeep Chimber <[email protected]>

* PI-2158 add unpaid work progress to new section of sentence object

Signed-off-by: Amardeep Chimber <[email protected]>

* PI-2158 add unpaid work progress to new section of sentence object

Signed-off-by: Amardeep Chimber <[email protected]>

* PI-2158 refactor sql to no longer be a native query

Signed-off-by: Amardeep Chimber <[email protected]>

* PI-2158 refactor sql to no longer be a native query

Signed-off-by: Amardeep Chimber <[email protected]>

* Formatting changes

* PI-2158 add scenario where no unpaid work has been completed

Signed-off-by: Amardeep Chimber <[email protected]>

* PI-2158 update integration test

Signed-off-by: Amardeep Chimber <[email protected]>

* Formatting changes

* PI-2158 apply review comments

Signed-off-by: Amardeep Chimber <[email protected]>

* PI-2158 apply review comments

Signed-off-by: Amardeep Chimber <[email protected]>

* PI-2158 apply review comments

Signed-off-by: Amardeep Chimber <[email protected]>

---------

Signed-off-by: Amardeep Chimber <[email protected]>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
  • Loading branch information
achimber-moj and github-actions[bot] authored May 14, 2024
1 parent d8258fa commit d99fa85
Show file tree
Hide file tree
Showing 9 changed files with 398 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,9 @@ class DataLoader(
PersonGenerator.ADD_OFF_2,
PersonGenerator.ADDITIONAL_OFFENCE_2,
PersonGenerator.MAIN_CAT_F,
PersonGenerator.MAIN_CAT_W,
PersonGenerator.REQUIREMENT,
PersonGenerator.REQUIREMENT_UNPAID_WORK,
PersonGenerator.REQUIREMENT_CONTACT_1,
PersonGenerator.REQUIREMENT_CONTACT_2,
PersonGenerator.REGISTER_TYPE_1,
Expand All @@ -143,11 +145,15 @@ class DataLoader(
PersonGenerator.REGISTRATION_REVIEW_3,
PersonGenerator.DEREGISTRATION_1,
PersonGenerator.MAIN_CAT_F_TYPE,
PersonGenerator.MAIN_CAT_W_TYPE,
PersonGenerator.NSI_BREACH_TYPE,
PersonGenerator.NSI_STATUS,
PersonGenerator.BREACH_PREVIOUS_ORDER_1,
PersonGenerator.BREACH_PREVIOUS_ORDER_2,
PersonGenerator.BREACH_ON_ACTIVE_ORDER
PersonGenerator.BREACH_ON_ACTIVE_ORDER,
UnpaidWorkApptGenerator.UNPAID_WORK_DETAILS_1,
UnpaidWorkApptGenerator.APPT1,
UnpaidWorkApptGenerator.APPT2,
)

personalDetailsData()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,13 @@ object PersonGenerator {
val MAIN_CAT_F_SUB_ID = IdGenerator.getAndIncrement();
val MAIN_CAT_F_TYPE = ReferenceData(MAIN_CAT_F_SUB_ID, "G03", "High Intensity")
val MAIN_CAT_F = RequirementMainCategory(IdGenerator.getAndIncrement(), "F", "Main", 1)
val REQUIREMENT = generateRequirement(ACTIVE_ORDER, MAIN_CAT_F_SUB_ID)
val REQUIREMENT = generateRequirement(ACTIVE_ORDER, MAIN_CAT_F_SUB_ID, mainCategory = MAIN_CAT_F)

val MAIN_CAT_W_SUB_ID = IdGenerator.getAndIncrement();
val MAIN_CAT_W_TYPE = ReferenceData(MAIN_CAT_W_SUB_ID, "W02", "Intensive")
val MAIN_CAT_W = RequirementMainCategory(IdGenerator.getAndIncrement(), "W", "Unpaid Work", 1107)
val REQUIREMENT_UNPAID_WORK = generateRequirement(ACTIVE_ORDER, MAIN_CAT_W_SUB_ID, mainCategory = MAIN_CAT_W)

val REQUIREMENT_CONTACT_1 = ContactGenerator.generateContact(
OVERVIEW,
ContactGenerator.APPT_CT_1,
Expand Down Expand Up @@ -314,7 +320,7 @@ object PersonGenerator {
subCategoryId: Long,
length: Long = 12,
notes: String? = "my notes",
mainCategory: RequirementMainCategory = MAIN_CAT_F,
mainCategory: RequirementMainCategory,
active: Boolean = true,
softDeleted: Boolean = false,
expectedStartDate: LocalDate? = LocalDate.now().minusDays(1),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
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.sentence.entity.UpwAppointment
import uk.gov.justice.digital.hmpps.integrations.delius.sentence.entity.UpwDetails

object UnpaidWorkApptGenerator {

val UNPAID_WORK_DETAILS_1 = UpwDetails(IdGenerator.getAndIncrement(), ACTIVE_ORDER, 0)

val APPT1 = UpwAppointment(IdGenerator.getAndIncrement(), 3, "Y", 0, UNPAID_WORK_DETAILS_1)
val APPT2 = UpwAppointment(IdGenerator.getAndIncrement(), 4, "Y", 1, UNPAID_WORK_DETAILS_1)
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,26 @@ class SentenceIntegrationTest {
null,
"my notes",
Rar(completed = 1, scheduled = 0, totalDays = 1)
),
Requirement(
"W",
LocalDate.now().minusDays(1),
LocalDate.now(),
LocalDate.now().minusDays(2),
LocalDate.now().minusDays(3),
null,
"Unpaid Work - Intensive",
12,
null,
"my notes",
null
)
),
listOf(
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)"
),
Sentence(
OffenceDetails(
Expand All @@ -99,7 +113,8 @@ class SentenceIntegrationTest {
Conviction(null, null, null, listOf()),
null,
listOf(),
listOf()
listOf(),
null
)
),
ProbationHistory(2, LocalDate.now().minusDays(7), 2, 2)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ data class Sentence(
val conviction: Conviction? = null,
val order: Order? = null,
val requirements: List<Requirement> = listOf(),
val courtDocuments: List<CourtDocument> = listOf()
val courtDocuments: List<CourtDocument> = listOf(),
val unpaidWorkProgress: String?
)
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,18 @@ interface RequirementRepository : JpaRepository<Requirement, Long> {
""", nativeQuery = true
)
fun getRequirements(id: Long, eventNumber: String): List<RequirementDetails>

@Query(
"""
SELECT SUM(r.length)
FROM Requirement r
JOIN r.mainCategory mc
JOIN r.disposal
WHERE r.disposal.id = :id
AND mc.code = 'W'
"""
)
fun sumTotalUnpaidWorkHoursByDisposal(id: Long): Long
}

fun RequirementRepository.getRar(disposalId: Long): Rar {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package uk.gov.justice.digital.hmpps.integrations.delius.sentence.entity

import jakarta.persistence.*
import org.hibernate.annotations.Immutable
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.data.jpa.repository.Query
import uk.gov.justice.digital.hmpps.integrations.delius.overview.entity.Disposal

@Entity
@Immutable
class UpwAppointment(
@Id
@Column(name = "upw_appointment_id")
val id: Long,

val minutesCredited: Long?,

@Column(columnDefinition = "char(1)")
val attended: String?,

val softDeleted: Long,

@JoinColumn(name = "upw_details_id")
@ManyToOne
val upwDetails: UpwDetails,
)

@Entity
@Immutable
class UpwDetails(
@Id
@Column(name = "upw_details_id")
val id: Long,

@JoinColumn(name = "disposal_id")
@ManyToOne
val disposal: Disposal,

val softDeleted: Long,
)

interface UpwAppointmentRepository : JpaRepository<UpwAppointment, Long> {

@Query(
"""
SELECT SUM(u.minutesCredited)
FROM UpwAppointment u
JOIN u.upwDetails upd
JOIN upd.disposal d
WHERE d.id = :id
AND u.softDeleted = 0
"""
)
fun calculateUnpaidTimeWorked(id: Long): Long
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package uk.gov.justice.digital.hmpps.service

import org.springframework.stereotype.Service
import uk.gov.justice.digital.hmpps.api.model.Name
import uk.gov.justice.digital.hmpps.api.model.overview.Order
import uk.gov.justice.digital.hmpps.api.model.overview.Rar
import uk.gov.justice.digital.hmpps.api.model.sentence.*
Expand All @@ -11,7 +10,9 @@ 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 java.time.Duration
import java.time.LocalDate
import kotlin.time.toKotlinDuration
import uk.gov.justice.digital.hmpps.integrations.delius.sentence.entity.AdditionalSentence as ExtraSentence

@Service
Expand All @@ -22,7 +23,8 @@ class SentenceService(
private val personRepository: PersonRepository,
private val requirementRepository: RequirementRepository,
private val documentRepository: DocumentRepository,
private val offenderManagerRepository: OffenderManagerRepository
private val offenderManagerRepository: OffenderManagerRepository,
private val upwAppointmentRepository: UpwAppointmentRepository
) {
fun getEvents(crn: String): SentenceOverview {
val person = personRepository.getPerson(crn)
Expand Down Expand Up @@ -62,16 +64,15 @@ class SentenceService(
additionalSentences.map { it.toAdditionalSentence() }
),
order = disposal?.toOrder(),
requirements = requirementRepository.getRequirements(id, eventNumber).map { it.toRequirement() },
courtDocuments = documentRepository.getCourtDocuments(id, eventNumber).map { it.toCourtDocument() }
requirements = requirementRepository.getRequirements(id, eventNumber)
.map { it.toRequirement() },
courtDocuments = documentRepository.getCourtDocuments(id, eventNumber).map { it.toCourtDocument() },
disposal?.id?.let { getUnpaidWorkTime(it) }
)

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

fun Person.toName() =
Name(forename, secondName, surname)

fun Disposal.toOrder() =
Order(description = type.description, length = length, startDate = date, endDate = expectedEndDate())

Expand Down Expand Up @@ -116,6 +117,33 @@ class SentenceService(
return null
}

fun getUnpaidWorkTime(disposalId: Long): String? {
val totalHoursOrdered = requirementRepository.sumTotalUnpaidWorkHoursByDisposal(disposalId)

if (totalHoursOrdered == 0L) {
return null
}

val durationInMinutes: Long = upwAppointmentRepository.calculateUnpaidTimeWorked(disposalId)

return getUnpaidWorkTime(totalHoursOrdered, durationInMinutes)
}

fun getUnpaidWorkTime(hoursOrdered: Long, minutesCredited: Long): String {
val totalMessage = hoursOrdered
.let { " (of $hoursOrdered hour${if (hoursOrdered != 1L) "s" else ""})" }

val creditedMessage = Duration.ofMinutes(minutesCredited).toKotlinDuration()
.toComponents { hours, minutes, _, _ ->
when {
hours == 0L -> "$minutes minute${if (minutes != 1) "s" else ""} completed"
minutes == 0 -> "$hours hour${if (hours != 1L) "s" else ""} completed"
else -> "$hours hour${if (hours != 1L) "s" else ""} $minutes minute${if (minutes != 1) "s" else ""} completed"
}
}
return "$creditedMessage$totalMessage"
}

fun CourtDocumentDetails.toCourtDocument(): CourtDocument = CourtDocument(id, lastSaved, documentName)

fun getMostRecentTerminatedDateFromInactiveEvents(events: List<Event>): LocalDate? {
Expand Down
Loading

0 comments on commit d99fa85

Please sign in to comment.