Skip to content

Commit

Permalink
Merge branch 'main' into PI-2575
Browse files Browse the repository at this point in the history
  • Loading branch information
joseph-bcl authored Oct 16, 2024
2 parents 990723e + 91159b9 commit dbb8639
Show file tree
Hide file tree
Showing 83 changed files with 1,422 additions and 179 deletions.
1 change: 1 addition & 0 deletions .github/workflows/access.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ on:
- '["workforce-allocations-to-delius"]'
- '["subject-access-requests-and-delius"]'
- '["common-platform-and-delius"]'
- '["ims-and-delius"]'
# ^ add new projects here
# GitHub Actions doesn't support dynamic choices, we must add each project here to enable manual deployments
# See https://github.com/community/community/discussions/11795
Expand Down
7 changes: 6 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ jobs:
- workforce-allocations-to-delius
- subject-access-requests-and-delius
- common-platform-and-delius
- ims-and-delius
# ^ add new projects here
# GitHub Actions doesn't support dynamic choices, we must add each project here to enable manual deployments
# See https://github.com/community/community/discussions/11795
Expand Down Expand Up @@ -106,7 +107,11 @@ jobs:

- name: Push images
if: env.push == 'true'
run: ./gradlew ${{ matrix.project }}:jib
uses: nick-fields/retry@7152eba30c6575329ac0576536151aca5a72780e # v3.0.0
with:
max_attempts: 3 # Pushing lots of new image versions at once can result in GitHub rate-limiting so we retry this step
timeout_minutes: 15
command: ./gradlew ${{ matrix.project }}:jib
env:
GITHUB_USERNAME: ${{ github.actor }}
GITHUB_PASSWORD: ${{ github.token }}
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ on:
- '["workforce-allocations-to-delius"]'
- '["subject-access-requests-and-delius"]'
- '["common-platform-and-delius"]'
- '["ims-and-delius"]'
# ^ add new projects here
# GitHub Actions doesn't support dynamic choices, we must add each project here to enable manual deployments
# See https://github.com/community/community/discussions/11795
Expand Down Expand Up @@ -157,3 +158,4 @@ jobs:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
with:
environment: ${{ inputs.environment }}
version: ${{ inputs.version }}
4 changes: 2 additions & 2 deletions .github/workflows/security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
echo >> projects/${{ matrix.project }}/.trivyignore
- name: Scan image
uses: aquasecurity/trivy-action@6e7b7d1fd3e4fef0c5fa8cce1229c54b2c9bd0d8 # v0.24.0
uses: aquasecurity/trivy-action@5681af892cd0f4997658e2bacc62bd0a894cf564 # v0.27.0
with:
image-ref: 'ghcr.io/ministryofjustice/hmpps-probation-integration-services/${{ matrix.project }}:latest'
ignore-unfixed: true
Expand All @@ -56,7 +56,7 @@ jobs:
sarif_file: 'trivy-results.sarif'

- name: Get Trivy results
uses: aquasecurity/trivy-action@6e7b7d1fd3e4fef0c5fa8cce1229c54b2c9bd0d8 # v0.24.0
uses: aquasecurity/trivy-action@5681af892cd0f4997658e2bacc62bd0a894cf564 # v0.27.0
with:
image-ref: 'ghcr.io/ministryofjustice/hmpps-probation-integration-services/${{ matrix.project }}:latest'
ignore-unfixed: true
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/service-catalogue.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ on:
- '["workforce-allocations-to-delius"]'
- '["subject-access-requests-and-delius"]'
- '["common-platform-and-delius"]'
- '["ims-and-delius"]'
# ^ add new projects here
# GitHub Actions doesn't support dynamic choices, we must add each project here to enable manual deployments
# See https://github.com/community/community/discussions/11795
Expand Down
12 changes: 12 additions & 0 deletions .idea/runConfigurations/ims_and_delius.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import uk.gov.justice.digital.hmpps.plugins.ClassPathPlugin
import uk.gov.justice.digital.hmpps.plugins.JibConfigPlugin

plugins {
kotlin("jvm") version "2.0.20"
kotlin("plugin.spring") version "2.0.20" apply false
kotlin("plugin.jpa") version "2.0.20" apply false
kotlin("jvm") version "2.0.21"
kotlin("plugin.spring") version "2.0.21" apply false
kotlin("plugin.jpa") version "2.0.21" apply false
id("org.springframework.boot") version "3.3.4" apply false
id("io.spring.dependency-management") version "1.1.6" apply false
id("com.gorylenko.gradle-git-properties") version "2.4.2" apply false
Expand All @@ -22,7 +22,7 @@ plugins {
val agentDeps: Configuration by configurations.creating

dependencies {
agentDeps("com.microsoft.azure:applicationinsights-agent:3.6.0")
agentDeps("com.microsoft.azure:applicationinsights-agent:3.6.1")
}

val copyAgentTask = project.tasks.register<Copy>("copyAgent") {
Expand Down
1 change: 1 addition & 0 deletions doc/tech-docs/source/services.html.md.erb
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,5 @@ weight: 20
* [Core Person Record And Delius](https://ministryofjustice.github.io/hmpps-probation-integration-services/tech-docs/projects/core-person-record-and-delius)
* [Subject Access Requests And Delius](https://ministryofjustice.github.io/hmpps-probation-integration-services/tech-docs/projects/subject-access-requests-and-delius)
* [Common Platform And Delius](https://ministryofjustice.github.io/hmpps-probation-integration-services/tech-docs/projects/common-platform-and-delius)
* [Ims And Delius](https://ministryofjustice.github.io/hmpps-probation-integration-services/tech-docs/projects/ims-and-delius)
<li style="display: none">^ add new projects here</li>
2 changes: 2 additions & 0 deletions projects/common-platform-and-delius/deploy/values-dev.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
enabled: false

generic-service:
ingress:
host: common-platform-and-delius-dev.hmpps.service.justice.gov.uk
Expand Down
2 changes: 2 additions & 0 deletions projects/common-platform-and-delius/deploy/values-preprod.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
enabled: false

generic-service:
ingress:
host: common-platform-and-delius-preprod.hmpps.service.justice.gov.uk
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@ import uk.gov.justice.digital.hmpps.data.generator.SentenceGenerator.generateCus
import uk.gov.justice.digital.hmpps.data.generator.SentenceGenerator.generateDisposal
import uk.gov.justice.digital.hmpps.data.generator.SentenceGenerator.generateEvent
import uk.gov.justice.digital.hmpps.data.generator.SentenceGenerator.generateOrderManager
import uk.gov.justice.digital.hmpps.data.repository.DatasetRepository
import uk.gov.justice.digital.hmpps.data.repository.DisposalRepository
import uk.gov.justice.digital.hmpps.data.repository.EventRepository
import uk.gov.justice.digital.hmpps.data.repository.OrderManagerRepository
import uk.gov.justice.digital.hmpps.data.repository.*
import uk.gov.justice.digital.hmpps.integrations.delius.custody.date.Custody
import uk.gov.justice.digital.hmpps.integrations.delius.custody.date.CustodyRepository
import uk.gov.justice.digital.hmpps.integrations.delius.custody.date.KeyDateRepository
Expand All @@ -37,6 +34,7 @@ class DataLoader(
private val eventRepository: EventRepository,
private val orderManagerRepository: OrderManagerRepository,
private val disposalRepository: DisposalRepository,
private val disposalTypeRepository: DisposalTypeRepository,
private val custodyRepository: CustodyRepository,
private val keyDateRepository: KeyDateRepository
) : ApplicationListener<ApplicationReadyEvent> {
Expand All @@ -57,6 +55,7 @@ class DataLoader(
referenceDataRepository.save(ReferenceDataGenerator.DEFAULT_CUSTODY_STATUS)
referenceDataRepository.saveAll(ReferenceDataGenerator.KEY_DATE_TYPES.values)
contactTypeRepository.save(ContactTypeGenerator.EDSS)
disposalTypeRepository.save(SentenceGenerator.DEFAULT_DISPOSAL_TYPE)

personRepository.save(PersonGenerator.DEFAULT)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,31 @@
package uk.gov.justice.digital.hmpps.data.generator

import uk.gov.justice.digital.hmpps.integrations.delius.custody.date.Custody
import uk.gov.justice.digital.hmpps.integrations.delius.custody.date.Disposal
import uk.gov.justice.digital.hmpps.integrations.delius.custody.date.Event
import uk.gov.justice.digital.hmpps.integrations.delius.custody.date.OrderManager
import uk.gov.justice.digital.hmpps.integrations.delius.custody.date.*
import uk.gov.justice.digital.hmpps.integrations.delius.custody.date.reference.ReferenceData
import uk.gov.justice.digital.hmpps.integrations.delius.person.Person
import java.time.LocalDate

object SentenceGenerator {
var DEFAULT_CUSTODY: Custody =
Custody(IdGenerator.getAndIncrement(), ReferenceDataGenerator.DEFAULT_CUSTODY_STATUS, "38339A")

fun generateEvent(person: Person = PersonGenerator.DEFAULT, number: String = "1") =
Event(IdGenerator.getAndIncrement(), number, person)
var DEFAULT_DISPOSAL_TYPE = generateDisposalType()

fun generateEvent(
person: Person = PersonGenerator.DEFAULT,
number: String = "1",
firstReleaseDate: LocalDate? = null
) =
Event(IdGenerator.getAndIncrement(), number, person, firstReleaseDate)

fun generateOrderManager(event: Event, providerId: Long = 1, teamId: Long = 2, staffId: Long = 3) =
OrderManager(IdGenerator.getAndIncrement(), event, providerId, teamId, staffId)

fun generateDisposal(event: Event) = Disposal(IdGenerator.getAndIncrement(), event)
fun generateDisposal(event: Event, type: DisposalType = DEFAULT_DISPOSAL_TYPE) =
Disposal(IdGenerator.getAndIncrement(), event, type)

fun generateDisposalType(requiredInformation: String = "L1") =
DisposalType(IdGenerator.getAndIncrement(), requiredInformation)

fun generateCustodialSentence(
custodyStatus: ReferenceData = ReferenceDataGenerator.DEFAULT_CUSTODY_STATUS,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ package uk.gov.justice.digital.hmpps.data.repository

import org.springframework.data.jpa.repository.JpaRepository
import uk.gov.justice.digital.hmpps.integrations.delius.custody.date.Disposal
import uk.gov.justice.digital.hmpps.integrations.delius.custody.date.DisposalType
import uk.gov.justice.digital.hmpps.integrations.delius.custody.date.Event
import uk.gov.justice.digital.hmpps.integrations.delius.custody.date.OrderManager

interface EventRepository : JpaRepository<Event, Long>
interface DisposalRepository : JpaRepository<Disposal, Long>
interface DisposalTypeRepository : JpaRepository<DisposalType, Long>
interface OrderManagerRepository : JpaRepository<OrderManager, Long>
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
package uk.gov.justice.digital.hmpps.integrations.delius.custody.date

import uk.gov.justice.digital.hmpps.integrations.prison.SentenceDetail
import java.time.LocalDate
import kotlin.reflect.KProperty

enum class CustodyDateType(val code: String, val field: KProperty<LocalDate?>) {
LICENCE_EXPIRY_DATE("LED", SentenceDetail::licenceExpiryDate),
AUTOMATIC_CONDITIONAL_RELEASE_DATE("ACR", SentenceDetail::conditionalReleaseDate),
PAROLE_ELIGIBILITY_DATE("PED", SentenceDetail::paroleEligibilityDate),
SENTENCE_EXPIRY_DATE("SED", SentenceDetail::sentenceExpiryDate),
EXPECTED_RELEASE_DATE("EXP", SentenceDetail::confirmedReleaseDate),
HDC_EXPECTED_DATE("HDE", SentenceDetail::homeDetentionCurfewEligibilityDate),
POST_SENTENCE_SUPERVISION_END_DATE("PSSED", SentenceDetail::postSentenceSupervisionEndDate),
SUSPENSION_DATE_IF_RESET("PR1", SentenceDetail::suspensionDateIfReset)
enum class CustodyDateType(val code: String) {
LICENCE_EXPIRY_DATE("LED"),
AUTOMATIC_CONDITIONAL_RELEASE_DATE("ACR"),
PAROLE_ELIGIBILITY_DATE("PED"),
SENTENCE_EXPIRY_DATE("SED"),
EXPECTED_RELEASE_DATE("EXP"),
HDC_EXPECTED_DATE("HDE"),
POST_SENTENCE_SUPERVISION_END_DATE("PSSED"),
SUSPENSION_DATE_IF_RESET("PR1")
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import org.springframework.web.client.RestClientResponseException
import uk.gov.justice.digital.hmpps.flags.FeatureFlags
import uk.gov.justice.digital.hmpps.integrations.delius.custody.date.CustodyDateType.*
import uk.gov.justice.digital.hmpps.integrations.delius.custody.date.contact.ContactService
import uk.gov.justice.digital.hmpps.integrations.delius.custody.date.reference.ReferenceDataRepository
import uk.gov.justice.digital.hmpps.integrations.delius.custody.date.reference.findKeyDateType
Expand All @@ -13,6 +14,8 @@ import uk.gov.justice.digital.hmpps.integrations.prison.Booking
import uk.gov.justice.digital.hmpps.integrations.prison.PrisonApiClient
import uk.gov.justice.digital.hmpps.integrations.prison.SentenceDetail
import uk.gov.justice.digital.hmpps.telemetry.TelemetryService
import java.time.LocalDate
import java.time.temporal.ChronoUnit.DAYS

@Service
@Transactional
Expand Down Expand Up @@ -51,39 +54,47 @@ class CustodyDateUpdateService(
}
val custody = custodyRepository.findCustodyById(custodyRepository.findForUpdate(custodyId))
val updated = calculateKeyDateChanges(sentenceDetail, custody)
.filter { it.type.code != CustodyDateType.SUSPENSION_DATE_IF_RESET.code || featureFlags.enabled("suspension-date-if-reset") }
if (updated.isEmpty()) {
telemetryService.trackEvent(
"KeyDatesUnchanged",
booking.telemetry(clientSource)
)
telemetryService.trackEvent("KeyDatesUnchanged", booking.telemetry(clientSource))
} else {
if (!dryRun) {
updated.ifNotEmpty(keyDateRepository::saveAll)
keyDateRepository.saveAll(updated)
contactService.createForKeyDateChanges(custody, updated)
}
telemetryService.trackEvent(
if (dryRun) "KeyDatesDryRun" else "KeyDatesUpdated",
booking.telemetry(clientSource) +
updated.associateBy({ it.type.code }, { it.date.toString() })
booking.telemetry(clientSource) + updated.associateBy({ it.type.code }, { it.date.toString() })
)
}
}

private fun List<KeyDate>.ifNotEmpty(code: (List<KeyDate>) -> Unit) = code(this)
private fun calculateKeyDateChanges(sentenceDetail: SentenceDetail, custody: Custody) = listOfNotNull(
custody.keyDate(LICENCE_EXPIRY_DATE.code, sentenceDetail.licenceExpiryDate),
custody.keyDate(AUTOMATIC_CONDITIONAL_RELEASE_DATE.code, sentenceDetail.conditionalReleaseDate),
custody.keyDate(PAROLE_ELIGIBILITY_DATE.code, sentenceDetail.paroleEligibilityDate),
custody.keyDate(SENTENCE_EXPIRY_DATE.code, sentenceDetail.sentenceExpiryDate),
custody.keyDate(EXPECTED_RELEASE_DATE.code, sentenceDetail.confirmedReleaseDate),
custody.keyDate(HDC_EXPECTED_DATE.code, sentenceDetail.homeDetentionCurfewEligibilityDate),
custody.keyDate(POST_SENTENCE_SUPERVISION_END_DATE.code, sentenceDetail.postSentenceSupervisionEndDate),
custody.keyDate(SUSPENSION_DATE_IF_RESET.code, suspensionDateIfReset(sentenceDetail, custody)),
)

private fun calculateKeyDateChanges(
sentenceDetail: SentenceDetail,
custody: Custody
): List<KeyDate> = CustodyDateType.entries.mapNotNull { cdt ->
cdt.field.getter.call(sentenceDetail)?.let {
val existing = custody.keyDates.find(cdt.code)
if (existing != null) {
existing.changeDate(it)
} else {
val kdt = referenceDataRepository.findKeyDateType(cdt.code)
KeyDate(null, custody, kdt, it)
}
fun suspensionDateIfReset(sentenceDetail: SentenceDetail, custody: Custody): LocalDate? = custody.disposal
?.takeIf { featureFlags.enabled("suspension-date-if-reset") }
?.takeIf { it.type.determinateSentence }
?.let {
val startDate = it.event.firstReleaseDate ?: sentenceDetail.conditionalReleaseDate ?: return null
val endDate = sentenceDetail.sentenceExpiryDate ?: return null
return if (startDate < endDate) startDate.plusDays(DAYS.between(startDate, endDate) * 2 / 3) else null
}

private fun Custody.keyDate(code: String, date: LocalDate?): KeyDate? = date?.let {
val existing = keyDates.find(code)
return if (existing != null) {
existing.changeDate(date)
} else {
val kdt = referenceDataRepository.findKeyDateType(code)
KeyDate(null, this, kdt, date)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
package uk.gov.justice.digital.hmpps.integrations.delius.custody.date

import jakarta.persistence.Column
import jakarta.persistence.Entity
import jakarta.persistence.Id
import jakarta.persistence.JoinColumn
import jakarta.persistence.ManyToOne
import jakarta.persistence.OneToMany
import jakarta.persistence.OneToOne
import jakarta.persistence.Table
import jakarta.persistence.*
import org.hibernate.annotations.Immutable
import org.hibernate.annotations.SQLRestriction
import uk.gov.justice.digital.hmpps.integrations.delius.custody.date.reference.ReferenceData
import uk.gov.justice.digital.hmpps.integrations.delius.person.Person
import java.time.LocalDate

@Immutable
@Entity
Expand All @@ -26,6 +20,9 @@ class Event(
@JoinColumn(name = "offender_id", nullable = false)
val person: Person,

@Column
val firstReleaseDate: LocalDate? = null,

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

Expand All @@ -51,13 +48,31 @@ class Disposal(
@JoinColumn(name = "event_id", updatable = false)
val event: Event,

@ManyToOne
@JoinColumn(name = "disposal_type_id")
val type: DisposalType,

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

@Column(updatable = false, columnDefinition = "NUMBER")
val softDeleted: Boolean = false
)

@Entity
@Immutable
@Table(name = "r_disposal_type")
data class DisposalType(
@Id
@Column(name = "disposal_type_id")
val id: Long,

@Column
val requiredInformation: String,
) {
val determinateSentence: Boolean get() = requiredInformation == "L1"
}

@Immutable
@Entity
class Custody(
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.prison

import com.fasterxml.jackson.annotation.JsonAlias
import java.time.LocalDate
import java.time.temporal.ChronoUnit.DAYS

class SentenceDetail(
val sentenceExpiryDate: LocalDate? = null,
Expand All @@ -16,9 +15,4 @@ class SentenceDetail(
val homeDetentionCurfewEligibilityDate: LocalDate? = null
) {
val conditionalReleaseDate = conditionalReleaseOverrideDate ?: conditionalReleaseDate

val suspensionDateIfReset =
if (conditionalReleaseDate != null && sentenceExpiryDate != null && sentenceExpiryDate > conditionalReleaseDate) {
conditionalReleaseDate.plusDays(DAYS.between(conditionalReleaseDate, sentenceExpiryDate) * 2 / 3)
} else null
}
Loading

0 comments on commit dbb8639

Please sign in to comment.