Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
* PI-2061

* PI-2061 added feature flag
  • Loading branch information
anthony-britton-moj authored Apr 19, 2024
1 parent dfed991 commit 4769a99
Show file tree
Hide file tree
Showing 8 changed files with 233 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ database:
password_key: /manage-offences-and-delius/db-password
tables:
- r_detailed_offence
- r_offence
sequences:
- detailed_offence_id_seq
- offence_id_seq

audit:
username: ManageOffencesAndDelius
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class DataLoader(
merge(DataGenerator.COURT_CATEGORY_SET)
merge(DataGenerator.COURT_CATEGORY)
merge(DataGenerator.EXISTING_OFFENCE)
merge(DataGenerator.HL_OFFENCE)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,16 @@ package uk.gov.justice.digital.hmpps.data.generator
import uk.gov.justice.digital.hmpps.entity.DetailedOffence
import uk.gov.justice.digital.hmpps.entity.ReferenceData
import uk.gov.justice.digital.hmpps.entity.ReferenceDataSet
import uk.gov.justice.digital.hmpps.entity.ReferenceOffence
import java.time.LocalDate

object DataGenerator {
val HL_OFFENCE = generateReferenceOffence(
code = "09100",
mainCategoryCode = "091",
subCategoryCode = "00",
ogrsOffenceCategoryId = 298456347L
)
val COURT_CATEGORY_SET = ReferenceDataSet(IdGenerator.getAndIncrement(), "COURT CATEGORY")
val COURT_CATEGORY = ReferenceData(IdGenerator.getAndIncrement(), "CS", "Summary Non-motoring", COURT_CATEGORY_SET)
val EXISTING_OFFENCE = DetailedOffence(
Expand All @@ -19,4 +26,36 @@ object DataGenerator {
startDate = LocalDate.of(2006, 5, 12),
endDate = null
)

fun generateReferenceOffence(
code: String,
description: String = "Description of $code",
selectable: Boolean = true,
mainCategoryCode: String,
mainCategoryDescription: String = "Main Category of $code",
mainCategoryAbbreviation: String? = mainCategoryDescription.take(50),
ogrsOffenceCategoryId: Long?,
subCategoryCode: String,
subCategoryDescription: String = "Sub Category of $code",
form20Code: String? = null,
schedule15SexualOffence: Boolean? = false,
schedule15ViolentOffence: Boolean? = false,
childAbduction: Boolean? = false,
id: Long = IdGenerator.getAndIncrement()
) = ReferenceOffence(
code,
description,
selectable,
mainCategoryCode,
mainCategoryDescription,
mainCategoryAbbreviation,
ogrsOffenceCategoryId,
subCategoryCode,
subCategoryDescription,
form20Code,
schedule15SexualOffence,
schedule15ViolentOffence,
childAbduction,
id
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"startDate": "2006-05-12",
"endDate": null,
"homeOfficeStatsCode": "091/55",
"homeOfficeDescription": "Obstructing a person home office description",
"changedDate": "2010-03-10T16:12:00",
"loadDate": "2023-06-05T10:01:42.867727",
"schedules": null,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
package uk.gov.justice.digital.hmpps

import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.Test
import org.mockito.kotlin.atMost
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.test.mock.mockito.MockBean
import uk.gov.justice.digital.hmpps.entity.OffenceRepository
import uk.gov.justice.digital.hmpps.flags.FeatureFlags
import uk.gov.justice.digital.hmpps.message.Notification
import uk.gov.justice.digital.hmpps.messaging.FF_CREATE_OFFENCE
import uk.gov.justice.digital.hmpps.messaging.HmppsChannelManager
import uk.gov.justice.digital.hmpps.resourceloader.ResourceLoader
import uk.gov.justice.digital.hmpps.telemetry.TelemetryService
Expand All @@ -22,12 +30,34 @@ internal class IntegrationTest {
@MockBean
lateinit var telemetryService: TelemetryService

@MockBean
lateinit var featureFlags: FeatureFlags

@Autowired
lateinit var offenceRepository: OffenceRepository

@Test
fun `update offence code`() {
whenever(featureFlags.enabled(FF_CREATE_OFFENCE)).thenReturn(true)
val notification = Notification(ResourceLoader.event("offence-changed"))

channelManager.getChannel(queueName).publishAndWait(notification)

verify(telemetryService).trackEvent("OffenceCodeUpdated", mapOf("offenceCode" to "AB06001"), mapOf())
verify()

channelManager.getChannel(queueName).publishAndWait(notification)

verify()
}

private fun verify() {
verify(telemetryService, atMost(2)).trackEvent("OffenceCodeUpdated", mapOf("offenceCode" to "AB06001"), mapOf())

val referenceOffence = offenceRepository.findOffenceByCode("09155")
assertNotNull(referenceOffence)

assertThat(referenceOffence?.description).isEqualTo("Obstructing a person home office description")
assertThat(referenceOffence?.mainCategoryCode).isEqualTo("091")
assertThat(referenceOffence?.subCategoryCode).isEqualTo("55")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package uk.gov.justice.digital.hmpps.entity

import jakarta.persistence.*
import jakarta.persistence.GenerationType.SEQUENCE
import org.hibernate.type.YesNoConverter
import org.springframework.data.annotation.CreatedBy
import org.springframework.data.annotation.CreatedDate
import org.springframework.data.annotation.LastModifiedBy
import org.springframework.data.annotation.LastModifiedDate
import org.springframework.data.jpa.domain.support.AuditingEntityListener
import org.springframework.data.jpa.repository.JpaRepository
import java.time.ZonedDateTime

@EntityListeners(AuditingEntityListener::class)
@Entity
@Table(name = "r_offence")
@SequenceGenerator(name = "offence_id_seq", sequenceName = "offence_id_seq", allocationSize = 1)
data class ReferenceOffence(

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

val description: String,

@Convert(converter = YesNoConverter::class)
val selectable: Boolean?,

@Column(columnDefinition = "char(3)")
val mainCategoryCode: String,

val mainCategoryDescription: String,
val mainCategoryAbbreviation: String?,

val ogrsOffenceCategoryId: Long?,

@Column(columnDefinition = "char(2)")
val subCategoryCode: String,

val subCategoryDescription: String,

@Column(name = "form_20_code")
val form20Code: String?,

@Convert(converter = YesNoConverter::class)
@Column(name = "schedule15_sexual_offence")
val schedule15SexualOffence: Boolean?,

@Convert(converter = YesNoConverter::class)
@Column(name = "schedule15_violent_offence")
val schedule15ViolentOffence: Boolean?,

@Convert(converter = YesNoConverter::class)
val childAbduction: Boolean?,

@Id
@GeneratedValue(strategy = SEQUENCE, generator = "offence_id_seq")
@Column(name = "offence_id")
val id: Long = 0
) {

@Column
val partitionAreaId: Long = 0

@Version
var rowVersion: Long = 0

@CreatedDate
@Column(name = "created_datetime")
var created: ZonedDateTime = ZonedDateTime.now()

@CreatedBy
@Column(name = "created_by_user_id")
var createdBy: Long = 0

@LastModifiedDate
@Column(name = "last_updated_datetime")
var lastModified: ZonedDateTime = ZonedDateTime.now()

@LastModifiedBy
@Column(name = "last_updated_user_id")
var lastModifiedBy: Long = 0
}

interface OffenceRepository : JpaRepository<ReferenceOffence, Long> {
fun findOffenceByCode(code: String): ReferenceOffence?
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package uk.gov.justice.digital.hmpps.messaging

import org.springframework.stereotype.Component
import org.springframework.transaction.annotation.Transactional
import uk.gov.justice.digital.hmpps.client.ManageOffencesClient
import uk.gov.justice.digital.hmpps.client.Offence
import uk.gov.justice.digital.hmpps.converter.NotificationConverter
import uk.gov.justice.digital.hmpps.entity.DetailedOffence
import uk.gov.justice.digital.hmpps.entity.OffenceRepository
import uk.gov.justice.digital.hmpps.entity.ReferenceOffence
import uk.gov.justice.digital.hmpps.exception.NotFoundException
import uk.gov.justice.digital.hmpps.flags.FeatureFlags
import uk.gov.justice.digital.hmpps.message.HmppsDomainEvent
import uk.gov.justice.digital.hmpps.message.Notification
import uk.gov.justice.digital.hmpps.repository.DetailedOffenceRepository
Expand All @@ -14,18 +18,26 @@ import uk.gov.justice.digital.hmpps.repository.findCourtCategory
import uk.gov.justice.digital.hmpps.telemetry.TelemetryService
import uk.gov.justice.digital.hmpps.telemetry.notificationReceived

const val FF_CREATE_OFFENCE = "manage-offences-create-offence"

@Component
class Handler(
override val converter: NotificationConverter<HmppsDomainEvent>,
private val telemetryService: TelemetryService,
private val manageOffencesClient: ManageOffencesClient,
private val detailedOffenceRepository: DetailedOffenceRepository,
private val referenceDataRepository: ReferenceDataRepository
private val offenceRepository: OffenceRepository,
private val referenceDataRepository: ReferenceDataRepository,
private val featureFlags: FeatureFlags
) : NotificationHandler<HmppsDomainEvent> {

@Transactional
override fun handle(notification: Notification<HmppsDomainEvent>) {
telemetryService.notificationReceived(notification)
val offence = manageOffencesClient.getOffence(notification.message.offenceCode)
if (featureFlags.enabled(FF_CREATE_OFFENCE)) {
offence.createOrMerge()
}
val existingEntity = detailedOffenceRepository.findByCode(offence.code)
detailedOffenceRepository.save(existingEntity.mergeWith(offence.newEntity))
telemetryService.trackEvent(
Expand Down Expand Up @@ -57,6 +69,52 @@ class Handler(
legislation = newEntity.legislation,
category = newEntity.category
) ?: newEntity

private fun Offence.createOrMerge() {
if (homeOfficeStatsCode != null && homeOfficeDescription != null) {
val highLevelOffence = checkNotNull(offenceRepository.findOffenceByCode(highLevelCode!!)) {
"High Level Offence not found: $highLevelCode"
}

val offence = offenceRepository.findOffenceByCode(homeOfficeCode).mergeWith(asReference(highLevelOffence))
offenceRepository.save(offence)
}
}
}

val HmppsDomainEvent.offenceCode get() = additionalInformation["offenceCode"] as String

val Offence.mainCategoryCode get() = homeOfficeStatsCode?.take(3)
val Offence.subCategoryCode get() = homeOfficeStatsCode?.takeLast(2)
val Offence.highLevelCode get() = mainCategoryCode?.let { it + "00" }
val Offence.homeOfficeCode get() = mainCategoryCode + subCategoryCode
fun Offence.asReference(highLevelOffence: ReferenceOffence) = ReferenceOffence(
code = homeOfficeCode,
description = homeOfficeDescription!!,
mainCategoryCode = mainCategoryCode!!,
selectable = false,
mainCategoryDescription = highLevelOffence.description,
mainCategoryAbbreviation = highLevelOffence.description.take(50),
ogrsOffenceCategoryId = highLevelOffence.ogrsOffenceCategoryId,
subCategoryCode = subCategoryCode!!,
subCategoryDescription = "$homeOfficeDescription - $subCategoryCode",
form20Code = highLevelOffence.form20Code,
childAbduction = null,
schedule15SexualOffence = null,
schedule15ViolentOffence = null
)

fun ReferenceOffence?.mergeWith(referenceOffence: ReferenceOffence) = this?.copy(
code = code,
description = description,
mainCategoryCode = mainCategoryCode,
mainCategoryDescription = mainCategoryDescription,
mainCategoryAbbreviation = mainCategoryAbbreviation,
ogrsOffenceCategoryId = ogrsOffenceCategoryId,
subCategoryCode = subCategoryCode,
subCategoryDescription = subCategoryDescription,
form20Code = form20Code,
schedule15SexualOffence = schedule15SexualOffence,
schedule15ViolentOffence = schedule15ViolentOffence,
childAbduction = childAbduction
) ?: referenceOffence
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package uk.gov.justice.digital.hmpps.messaging

import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.Matchers.equalTo
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import org.junit.jupiter.api.extension.ExtendWith
Expand All @@ -16,7 +17,9 @@ import uk.gov.justice.digital.hmpps.client.Offence
import uk.gov.justice.digital.hmpps.converter.NotificationConverter
import uk.gov.justice.digital.hmpps.data.generator.DataGenerator.COURT_CATEGORY
import uk.gov.justice.digital.hmpps.data.generator.DataGenerator.EXISTING_OFFENCE
import uk.gov.justice.digital.hmpps.entity.OffenceRepository
import uk.gov.justice.digital.hmpps.exception.NotFoundException
import uk.gov.justice.digital.hmpps.flags.FeatureFlags
import uk.gov.justice.digital.hmpps.message.HmppsDomainEvent
import uk.gov.justice.digital.hmpps.message.Notification
import uk.gov.justice.digital.hmpps.repository.DetailedOffenceRepository
Expand All @@ -40,12 +43,23 @@ internal class HandlerTest {
@Mock
lateinit var detailedOffenceRepository: DetailedOffenceRepository

@Mock
lateinit var offenceRepository: OffenceRepository

@Mock
lateinit var referenceDataRepository: ReferenceDataRepository

@Mock
lateinit var featureFlags: FeatureFlags

@InjectMocks
lateinit var handler: Handler

@BeforeEach
fun setup() {
whenever(featureFlags.enabled(FF_CREATE_OFFENCE)).thenReturn(false)
}

@Test
fun `missing reference data is thrown`() {
val notification = Notification(ResourceLoader.event("offence-changed"))
Expand Down

0 comments on commit 4769a99

Please sign in to comment.