Skip to content

Commit

Permalink
PI-2145 Generate monthly initial allocations report to Slack (#3718)
Browse files Browse the repository at this point in the history
* PI-2145 Initial allocations report CSV endpoint

* Added cron job to pull report and upload to Slack
  • Loading branch information
marcus-bcl authored May 8, 2024
1 parent 88db8c6 commit cad5d00
Show file tree
Hide file tree
Showing 22 changed files with 414 additions and 20 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
VALIDATE_XML: true
VALIDATE_YAML: true
LINTER_RULES_PATH: /
FILTER_REGEX_EXCLUDE: .+templates/.+yml # yamlint doesn't like Helm templating
FILTER_REGEX_EXCLUDE: .*templates/.*.ya?ml
GITHUB_ACTIONS_CONFIG_FILE: .github/actionlint.yml
GITHUB_ACTIONS_COMMAND_ARGS: -ignore=SC.+:info:.+
GITHUB_TOKEN: ${{ github.token }}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,15 @@ spec:
serviceAccountName: person-search-index-from-delius
containers:
- name: contact-reindex
image: ghcr.io/ministryofjustice/hmpps-probation-integration-services/person-search-index-from-delius:{{ .Values.version }}
image: "ghcr.io/ministryofjustice/hmpps-probation-integration-services/person-search-index-from-delius:{{ .Values.version }}"
securityContext:
capabilities:
drop:
- ALL
runAsNonRoot: true
allowPrivilegeEscalation: false
seccompProfile:
type: RuntimeDefault
resources:
requests:
memory: 2Gi
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,15 @@ spec:
serviceAccountName: person-search-index-from-delius
containers:
- name: person-reindex
image: ghcr.io/ministryofjustice/hmpps-probation-integration-services/person-search-index-from-delius:{{ .Values.version }}
image: "ghcr.io/ministryofjustice/hmpps-probation-integration-services/person-search-index-from-delius:{{ .Values.version }}"
securityContext:
capabilities:
drop:
- ALL
runAsNonRoot: true
allowPrivilegeEscalation: false
seccompProfile:
type: RuntimeDefault
resources:
requests:
memory: 2Gi
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ spec:
containers:
- name: update-prison-identifiers
image: "ghcr.io/ministryofjustice/hmpps-probation-integration-services/prison-identifier-and-delius:{{ .Values.version }}"
securityContext:
capabilities:
drop:
- ALL
runAsNonRoot: true
allowPrivilegeEscalation: false
seccompProfile:
type: RuntimeDefault
resources:
requests:
memory: "1Gi"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ spec:
containers:
- name: dlq-redrive
image: "ghcr.io/ministryofjustice/hmpps-probation-integration-services/redrive-dead-letter-queues:{{ .Values.version }}"
securityContext:
capabilities:
drop:
- ALL
runAsNonRoot: true
allowPrivilegeEscalation: false
seccompProfile:
type: RuntimeDefault
resources:
requests:
memory: 100Mi
Expand Down
1 change: 1 addition & 0 deletions projects/workforce-allocations-to-delius/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ dependencies {
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-csv")
implementation(libs.springdoc)
implementation(libs.opentelemetry.annotations)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
{{- $config := index .Values "initial-allocations-report" | default dict -}}
{{- if $config.enabled | default false -}}
apiVersion: v1
kind: ConfigMap
metadata:
name: initial-allocations-report-script
data:
script.sh: |
#!/bin/bash
set -euo pipefail
date=$(date +%Y-%m-%d)
filename=initial-allocations-$date.csv
echo Getting HMPPS Auth token...
hmpps_auth_token=$(curl -fsSL -XPOST -u "$CLIENT_ID:$CLIENT_SECRET" '{{ index .Values "generic-service" "env" "SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_HMPPS-AUTH_TOKEN-URI" }}?grant_type=client_credentials' | jq -r .access_token)
echo Downloading report...
curl -fsSL -H "Authorization: Bearer $hmpps_auth_token" https://{{ index .Values "generic-service" "ingress" "host" }}/initial-allocations.csv > "/tmp/$filename"
echo Downloaded report with $(wc -l < "/tmp/$filename") rows
echo Starting file upload...
file_details=$(curl -fsSL -XPOST -F "token=$SLACK_TOKEN" -F "filename=$filename" -F 'snippet_type=csv' -F "length=$(wc -c < "/tmp/$filename")" https://slack.com/api/files.getUploadURLExternal)
echo Got file upload details: "$file_details"
file_id=$(echo "$file_details" | jq -r .file_id)
upload_url=$(echo "$file_details" | jq -r .upload_url)
echo Uploading file...
curl -fsSL -F "file=@/tmp/$filename" "$upload_url"
echo Sending message...
curl -fsSL -F "token=$SLACK_TOKEN" -F "initial_comment=Initial Allocations Report ($(date '+%d/%m/%Y'))" -F "files=[{\"id\":\"$file_id\"}]" -F "channel_id={{ index .Values "initial-allocations-report" "channel_id" }}" https://slack.com/api/files.completeUploadExternal
echo Uploaded report to Slack
---
apiVersion: batch/v1
kind: CronJob
metadata:
name: initial-allocations-report
spec:
schedule: {{ index .Values "initial-allocations-report" "schedule" }}
concurrencyPolicy: Forbid
failedJobsHistoryLimit: 1
successfulJobsHistoryLimit: 1
jobTemplate:
spec:
template:
spec:
serviceAccountName: workforce-allocations-to-delius
volumes:
- name: script-volume
configMap:
name: initial-allocations-report-script
containers:
- name: generate-report
image: "ghcr.io/ministryofjustice/hmpps-devops-tools:latest"
command: [ "bash", "/script.sh" ]
volumeMounts:
- name: script-volume
mountPath: /script.sh
subPath: script.sh
env:
- name: CLIENT_ID
valueFrom:
secretKeyRef:
name: workforce-allocations-to-delius-client-credentials
key: CLIENT_ID
optional: false
- name: CLIENT_SECRET
valueFrom:
secretKeyRef:
name: workforce-allocations-to-delius-client-credentials
key: CLIENT_SECRET
optional: false
- name: SLACK_TOKEN
valueFrom:
secretKeyRef:
name: slack-bot
key: TOKEN
optional: false
securityContext:
capabilities:
drop:
- ALL
runAsNonRoot: true
allowPrivilegeEscalation: false
seccompProfile:
type: RuntimeDefault
restartPolicy: Never
{{- end -}}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ generic-service:
SENTRY_ENVIRONMENT: dev
SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_HMPPS-AUTH_TOKEN-URI: http://hmpps-auth.hmpps-auth-dev.svc.cluster.local/auth/oauth/token
SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_JWK_SET_URI: http://hmpps-auth.hmpps-auth-dev.svc.cluster.local/auth/.well-known/jwks.json
SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_ISSUER_URI: https://sign-in-dev.hmpps.service.justice.gov.uk/auth/issuer
INTEGRATIONS_ALFRESCO_URL: https://hmpps-delius-alfresco-test.apps.live.cloud-platform.service.justice.gov.uk/alfresco/service/noms-spg/

SPRING_DATASOURCE_HIKARI_MAXIMUMPOOLSIZE: 5
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ generic-service:
SENTRY_ENVIRONMENT: preprod
SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_HMPPS-AUTH_TOKEN-URI: http://hmpps-auth.hmpps-auth-preprod.svc.cluster.local/auth/oauth/token
SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_JWK_SET_URI: http://hmpps-auth.hmpps-auth-preprod.svc.cluster.local/auth/.well-known/jwks.json
SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_ISSUER_URI: https://sign-in-preprod.hmpps.service.justice.gov.uk/auth/issuer
INTEGRATIONS_ALFRESCO_URL: https://alfresco.pre-prod.delius.probation.hmpps.dsd.io/alfresco/service/noms-spg/

generic-prometheus-alerts:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,9 @@ generic-service:
SENTRY_ENVIRONMENT: prod
SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_HMPPS-AUTH_TOKEN-URI: http://hmpps-auth.hmpps-auth-prod.svc.cluster.local/auth/oauth/token
SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_JWK_SET_URI: http://hmpps-auth.hmpps-auth-prod.svc.cluster.local/auth/.well-known/jwks.json
SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_ISSUER_URI: https://sign-in.hmpps.service.justice.gov.uk/auth/issuer
INTEGRATIONS_ALFRESCO_URL: https://alfresco.probation.service.justice.gov.uk/alfresco/service/noms-spg/

initial-allocations-report:
enabled: true
schedule: "30 7 1 * *" # The first of the month at 7:30am
channel_id: C035YK9FFK4 # topic-pi-workforce-allocation
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,10 @@ import org.springframework.boot.context.event.ApplicationReadyEvent
import org.springframework.context.ApplicationListener
import org.springframework.stereotype.Component
import uk.gov.justice.digital.hmpps.audit.repository.BusinessInteractionRepository
import uk.gov.justice.digital.hmpps.data.generator.*
import uk.gov.justice.digital.hmpps.data.generator.BusinessInteractionGenerator.ADD_EVENT_ALLOCATION
import uk.gov.justice.digital.hmpps.data.generator.BusinessInteractionGenerator.ADD_PERSON_ALLOCATION
import uk.gov.justice.digital.hmpps.data.generator.BusinessInteractionGenerator.CREATE_COMPONENT_TRANSFER
import uk.gov.justice.digital.hmpps.data.generator.ContactTypeGenerator
import uk.gov.justice.digital.hmpps.data.generator.CourtReportTypeGenerator
import uk.gov.justice.digital.hmpps.data.generator.DatasetGenerator
import uk.gov.justice.digital.hmpps.data.generator.OffenceGenerator
import uk.gov.justice.digital.hmpps.data.generator.ProviderGenerator
import uk.gov.justice.digital.hmpps.data.generator.ReferenceDataGenerator
import uk.gov.justice.digital.hmpps.data.generator.RegisterTypeGenerator
import uk.gov.justice.digital.hmpps.data.generator.RequirementAdditionalMainCategoryGenerator
import uk.gov.justice.digital.hmpps.data.generator.RequirementMainCategoryGenerator
import uk.gov.justice.digital.hmpps.data.generator.StaffGenerator
import uk.gov.justice.digital.hmpps.data.generator.TeamGenerator
import uk.gov.justice.digital.hmpps.data.generator.UserGenerator
import uk.gov.justice.digital.hmpps.data.repository.*
import uk.gov.justice.digital.hmpps.integrations.delius.allocations.entity.ReferenceDataRepository
import uk.gov.justice.digital.hmpps.integrations.delius.contact.ContactTypeRepository
Expand Down Expand Up @@ -48,7 +37,8 @@ class AllocationsDataLoader(
private val caseViewDataLoader: CaseViewDataLoader,
private val registerTypeRepository: RegisterTypeRepository,
private val limitedAccessDataLoader: LimitedAccessDataLoader,
private val registrationDataLoader: RegistrationDataLoader
private val registrationDataLoader: RegistrationDataLoader,
private val existingAllocationsDataLoader: ExistingAllocationsDataLoader,
) : ApplicationListener<ApplicationReadyEvent> {

@PostConstruct
Expand Down Expand Up @@ -142,5 +132,6 @@ class AllocationsDataLoader(
caseViewDataLoader.loadData()
limitedAccessDataLoader.loadData()
registrationDataLoader.loadData()
existingAllocationsDataLoader.loadData()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package uk.gov.justice.digital.hmpps.data

import jakarta.persistence.EntityManager
import jakarta.transaction.Transactional
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
import org.springframework.stereotype.Component
import uk.gov.justice.digital.hmpps.data.generator.*
import uk.gov.justice.digital.hmpps.integrations.delius.event.OrderManagerRepository

@Component
@ConditionalOnProperty("seed.database")
class ExistingAllocationsDataLoader(
private val orderManagerRepository: OrderManagerRepository,
private val existingAllocationsRefDataLoader: ExistingAllocationsRefDataLoader,
) {
fun loadData() {
existingAllocationsRefDataLoader.loadData()
orderManagerRepository.save(OrderManagerGenerator.UNALLOCATED)
orderManagerRepository.save(OrderManagerGenerator.INITIAL_ALLOCATION)
}
}

@Component
@Transactional
class ExistingAllocationsRefDataLoader(private val entityManager: EntityManager) {
fun loadData() {
entityManager.persist(ProviderGenerator.PDU)
entityManager.persist(ProviderGenerator.LAU)
entityManager.persist(TeamGenerator.TEAM_IN_LAU)
entityManager.persist(StaffGenerator.ALLOCATED)
entityManager.persist(EventGenerator.HAS_INITIAL_ALLOCATION)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package uk.gov.justice.digital.hmpps.data.entity

import jakarta.persistence.*
import org.hibernate.annotations.Immutable
import uk.gov.justice.digital.hmpps.integrations.delius.provider.StaffWithUser
import uk.gov.justice.digital.hmpps.integrations.delius.provider.Team
import java.time.ZonedDateTime

@Entity
@Immutable
@Table(name = "borough")
class ProbationDeliveryUnit(
@Id
@Column(name = "borough_id")
val id: Long,
val code: String,
val description: String,
)

@Entity
@Immutable
@Table(name = "district")
class LocalAdminUnit(
@Id
@Column(name = "district_id")
val id: Long,

@ManyToOne
@JoinColumn(name = "borough_id")
val pdu: ProbationDeliveryUnit,
)

@Entity
@Immutable
@Table(name = "team")
class TeamWithLocalAdminUnit(
@Id
@Column(name = "team_id")
val id: Long,

@Column(name = "code", columnDefinition = "char(6)")
val code: String,

@Column(name = "probation_area_id")
val providerId: Long,

val description: String,

@Column(name = "end_date")
val endDate: ZonedDateTime? = null,

@ManyToMany(mappedBy = "teams")
val staff: List<StaffWithUser> = listOf(),

@ManyToOne
@JoinColumn(name = "district_id")
val localAdminUnit: LocalAdminUnit? = null,
)

fun Team.withLocalAdminUnit(localAdminUnit: LocalAdminUnit) =
TeamWithLocalAdminUnit(id, code, providerId, description, endDate, staff, localAdminUnit)

fun TeamWithLocalAdminUnit.toTeam() = Team(id, code, providerId, description, endDate, staff)
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ object EventGenerator {
val NEW = generate(eventNumber = "2")
val HISTORIC = generate(eventNumber = "3")
val DELETED = generate(eventNumber = "1", softDeleted = true)
val HAS_INITIAL_ALLOCATION = generate(eventNumber = "4")
val INACTIVE = generate(eventNumber = "99", active = false)

val CASE_VIEW = forCaseView()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package uk.gov.justice.digital.hmpps.data.generator

import uk.gov.justice.digital.hmpps.data.entity.toTeam
import uk.gov.justice.digital.hmpps.data.generator.RequirementManagerGenerator.build
import uk.gov.justice.digital.hmpps.datetime.EuropeLondon
import uk.gov.justice.digital.hmpps.integrations.delius.event.OrderManager
import uk.gov.justice.digital.hmpps.integrations.delius.provider.Provider
import uk.gov.justice.digital.hmpps.integrations.delius.provider.Staff
Expand All @@ -18,6 +20,19 @@ object OrderManagerGenerator {
startDateTime = ManagerGenerator.START_DATE_TIME.minusDays(2),
staff = StaffGenerator.STAFF_FOR_INACTIVE_EVENT
)
var INITIAL_ALLOCATION = generate(
startDateTime = ZonedDateTime.of(2024, 5, 7, 12, 0, 0, 0, EuropeLondon),
eventId = EventGenerator.HAS_INITIAL_ALLOCATION.id,
staff = StaffGenerator.ALLOCATED,
team = TeamGenerator.TEAM_IN_LAU.toTeam()
)
var UNALLOCATED = generate(
startDateTime = ZonedDateTime.of(2024, 5, 1, 12, 0, 0, 0, EuropeLondon),
eventId = EventGenerator.HAS_INITIAL_ALLOCATION.id,
team = TeamGenerator.TEAM_IN_LAU.toTeam()
).also {
it.endDate = ManagerGenerator.START_DATE_TIME
}

fun generate(
id: Long = IdGenerator.getAndIncrement(),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package uk.gov.justice.digital.hmpps.data.generator

import uk.gov.justice.digital.hmpps.data.entity.LocalAdminUnit
import uk.gov.justice.digital.hmpps.data.entity.ProbationDeliveryUnit
import uk.gov.justice.digital.hmpps.integrations.delius.provider.Provider

object ProviderGenerator {
Expand All @@ -8,4 +10,6 @@ object ProviderGenerator {
"N02",
"NPS North East"
)
val PDU = ProbationDeliveryUnit(id = IdGenerator.getAndIncrement(), code = "PDU1", description = "Some PDU")
val LAU = LocalAdminUnit(id = IdGenerator.getAndIncrement(), pdu = PDU)
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ object StaffGenerator {
"John",
"Smith"
)
val ALLOCATED = generateStaff(
"TEST01",
"John",
"Smith"
)
val STAFF_WITH_USER = generateStaffWithUser(
"${TeamGenerator.ALLOCATION_TEAM.code}1",
"Joe",
Expand Down
Loading

0 comments on commit cad5d00

Please sign in to comment.