diff --git a/projects/domain-events-and-delius/build.gradle.kts b/projects/domain-events-and-delius/build.gradle.kts index 639524d398..75baff2a70 100644 --- a/projects/domain-events-and-delius/build.gradle.kts +++ b/projects/domain-events-and-delius/build.gradle.kts @@ -6,6 +6,7 @@ dependencies { implementation(project(":libs:audit")) implementation(project(":libs:commons")) implementation(project(":libs:messaging")) + implementation(project(":libs:oauth-server")) implementation("org.springframework.boot:spring-boot-starter-actuator") implementation("org.springframework.boot:spring-boot-starter-data-jpa") diff --git a/projects/domain-events-and-delius/deploy/values-dev.yml b/projects/domain-events-and-delius/deploy/values-dev.yml index b474201cc0..3f4543ee53 100644 --- a/projects/domain-events-and-delius/deploy/values-dev.yml +++ b/projects/domain-events-and-delius/deploy/values-dev.yml @@ -6,6 +6,7 @@ generic-service: enabled: true env: + DOMAIN_EVENTS_BASE_URL: domain-events-and-delius-dev.hmpps.service.justice.gov.uk SENTRY_ENVIRONMENT: dev LOGGING_LEVEL_UK_GOV_DIGITAL_JUSTICE_HMPPS: DEBUG diff --git a/projects/domain-events-and-delius/deploy/values-preprod.yml b/projects/domain-events-and-delius/deploy/values-preprod.yml index 4c458a8231..4e69372d01 100644 --- a/projects/domain-events-and-delius/deploy/values-preprod.yml +++ b/projects/domain-events-and-delius/deploy/values-preprod.yml @@ -6,6 +6,7 @@ generic-service: enabled: true env: + DOMAIN_EVENTS_BASE_URL: domain-events-and-delius-preprod.hmpps.service.justice.gov.uk SENTRY_ENVIRONMENT: preprod generic-prometheus-alerts: diff --git a/projects/domain-events-and-delius/deploy/values-prod.yml b/projects/domain-events-and-delius/deploy/values-prod.yml index e1a2f5b5d5..b67a680b65 100644 --- a/projects/domain-events-and-delius/deploy/values-prod.yml +++ b/projects/domain-events-and-delius/deploy/values-prod.yml @@ -3,4 +3,5 @@ generic-service: host: domain-events-and-delius.hmpps.service.justice.gov.uk env: + DOMAIN_EVENTS_BASE_URL: domain-events-and-delius.hmpps.service.justice.gov.uk SENTRY_ENVIRONMENT: prod \ No newline at end of file diff --git a/projects/domain-events-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt b/projects/domain-events-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt index 08c90d5672..bfa7495ef2 100644 --- a/projects/domain-events-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt +++ b/projects/domain-events-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/DataLoader.kt @@ -1,22 +1,29 @@ package uk.gov.justice.digital.hmpps.data import jakarta.annotation.PostConstruct +import jakarta.persistence.EntityManager import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty import org.springframework.boot.context.event.ApplicationReadyEvent import org.springframework.context.ApplicationListener import org.springframework.stereotype.Component +import org.springframework.transaction.annotation.Transactional +import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator import uk.gov.justice.digital.hmpps.data.generator.UserGenerator import uk.gov.justice.digital.hmpps.user.AuditUserRepository @Component @ConditionalOnProperty("seed.database") class DataLoader( - private val auditUserRepository: AuditUserRepository + private val auditUserRepository: AuditUserRepository, + private val em: EntityManager ) : ApplicationListener { @PostConstruct fun saveAuditUser() { auditUserRepository.save(UserGenerator.AUDIT_USER) } - override fun onApplicationEvent(event: ApplicationReadyEvent) {} + @Transactional + override fun onApplicationEvent(event: ApplicationReadyEvent) { + em.persist(PersonGenerator.ENGAGEMENT_CREATED) + } } diff --git a/projects/domain-events-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/PersonGenerator.kt b/projects/domain-events-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/PersonGenerator.kt new file mode 100644 index 0000000000..2aba3ab661 --- /dev/null +++ b/projects/domain-events-and-delius/src/dev/kotlin/uk/gov/justice/digital/hmpps/data/generator/PersonGenerator.kt @@ -0,0 +1,21 @@ +package uk.gov.justice.digital.hmpps.data.generator + +import uk.gov.justice.digital.hmpps.integrations.delius.person.entity.Person +import java.time.LocalDate + +object PersonGenerator { + val ENGAGEMENT_CREATED = + generate("X789654", "Bernard", "Shepherd", LocalDate.of(1977, 10, 9), pnc = "1977/9999748M") + + fun generate( + crn: String, + forename: String, + surname: String, + dateOfBirth: LocalDate, + secondName: String? = null, + thirdName: String? = null, + pnc: String? = null, + softDeleted: Boolean = false, + id: Long = IdGenerator.getAndIncrement() + ) = Person(crn, pnc, forename, secondName, thirdName, surname, dateOfBirth, softDeleted, id) +} diff --git a/projects/domain-events-and-delius/src/dev/resources/local-public-key.pub b/projects/domain-events-and-delius/src/dev/resources/local-public-key.pub new file mode 100644 index 0000000000..b19c1e9863 --- /dev/null +++ b/projects/domain-events-and-delius/src/dev/resources/local-public-key.pub @@ -0,0 +1,6 @@ +-----BEGIN PUBLIC KEY----- +MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDju2wS/xXRfjdRI9thM2yJ7xO4 +cy5o8eJ1tljIrqJvKcdsmuflNv7IXGZP4OIQBhALkS3CQxIhBl9gNAtyu2AdYUdn +bSlBS5qLtLg2EoPn2GyGSwRiZCmZcmDsHdn8DX0zNCgZN9i/B/yCL0gXgvHRGEqP +QCtNM3Urqkvn97LVjQIDAQAB +-----END PUBLIC KEY----- \ No newline at end of file diff --git a/projects/domain-events-and-delius/src/dev/resources/messages/probation-case.engagement.created-attributes.json b/projects/domain-events-and-delius/src/dev/resources/messages/probation-case.engagement.created-attributes.json new file mode 100644 index 0000000000..5a3b0c5a0d --- /dev/null +++ b/projects/domain-events-and-delius/src/dev/resources/messages/probation-case.engagement.created-attributes.json @@ -0,0 +1,6 @@ +{ + "eventType": { + "Type": "String", + "Value": "probation-case.engagement.created" + } +} \ No newline at end of file diff --git a/projects/domain-events-and-delius/src/dev/resources/messages/probation-case.engagement.created.json b/projects/domain-events-and-delius/src/dev/resources/messages/probation-case.engagement.created.json new file mode 100644 index 0000000000..e5884c7d90 --- /dev/null +++ b/projects/domain-events-and-delius/src/dev/resources/messages/probation-case.engagement.created.json @@ -0,0 +1,15 @@ +{ + "eventType": "probation-case.engagement.created", + "version": 1, + "description": "A new probation case has been created", + "detailUrl": "https://example.com", + "occurredAt": "2023-09-20T16:05:59.442+01:00", + "personReference": { + "identifiers": [ + { + "type": "CRN", + "value": "X789654" + } + ] + } +} \ No newline at end of file diff --git a/projects/domain-events-and-delius/src/dev/resources/simulations/__files/hmpps-auth-token-body.json b/projects/domain-events-and-delius/src/dev/resources/simulations/__files/hmpps-auth-token-body.json new file mode 100644 index 0000000000..a595f9be58 --- /dev/null +++ b/projects/domain-events-and-delius/src/dev/resources/simulations/__files/hmpps-auth-token-body.json @@ -0,0 +1,10 @@ +{ + "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJwcm9iYXRpb24taW50ZWdyYXRpb24tZGV2IiwiZ3JhbnRfdHlwZSI6ImNsaWVudF9jcmVkZW50aWFscyIsInVzZXJfbmFtZSI6InByb2JhdGlvbi1pbnRlZ3JhdGlvbi1kZXYiLCJzY29wZSI6WyJyZWFkIl0sImF1dGhfc291cmNlIjoibm9uZSIsImlzcyI6Imh0dHBzOi8vc2lnbi1pbi1kZXYuaG1wcHMuc2VydmljZS5qdXN0aWNlLmdvdi51ay9hdXRoL2lzc3VlciIsImV4cCI6OTk5OTk5OTk5OSwiYXV0aG9yaXRpZXMiOlsiUk9MRV9WSUVXX1BST0JBVElPTl9DQVNFX0VOR0FHRU1FTlRfQ1JFQVRFRCJdLCJqdGkiOiIyNUR1Um4xLWh5SFpld0xjZEpKeHdWTDAzS1UiLCJjbGllbnRfaWQiOiJwcm9iYXRpb24taW50ZWdyYXRpb24tZGV2IiwiaWF0IjoxNjYzNzU3MzExfQ.w-fJ016upnUJKTPCyGVuIupXRESglhmdD3cvhCyeCU67c8bOdb6gVgpjCMsCxuP-Z5EkIMjLmIe_XvxZQPuLtExgpBbfQ596JMWqco5E6r53Fp8n7BMqR54xhxVoTJRk8em8lrIwGgNnRv9Ee2zhidtxlP2f3GS1G7F48oSTPuE", + "token_type": "bearer", + "expires_in": 9999999999, + "scope": "read write", + "sub": "probation-integration-dev", + "auth_source": "none", + "jti": "fN29JHJy1N7gcYvqe-8B_k5T0mA", + "iss": "https://sign-in-dev.hmpps.service.justice.gov.uk/auth/issuer" +} \ No newline at end of file diff --git a/projects/domain-events-and-delius/src/dev/resources/simulations/mappings/hmpps-auth.json b/projects/domain-events-and-delius/src/dev/resources/simulations/mappings/hmpps-auth.json new file mode 100644 index 0000000000..8a34b1316e --- /dev/null +++ b/projects/domain-events-and-delius/src/dev/resources/simulations/mappings/hmpps-auth.json @@ -0,0 +1,13 @@ +{ + "request": { + "method": "POST", + "urlPath": "/auth/oauth/token" + }, + "response": { + "headers": { + "Content-Type": "application/json" + }, + "status": 200, + "bodyFileName": "hmpps-auth-token-body.json" + } +} \ No newline at end of file diff --git a/projects/domain-events-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/EngagementCreatedTest.kt b/projects/domain-events-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/EngagementCreatedTest.kt new file mode 100644 index 0000000000..824e3a94f4 --- /dev/null +++ b/projects/domain-events-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/EngagementCreatedTest.kt @@ -0,0 +1,52 @@ +package uk.gov.justice.digital.hmpps + +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.module.kotlin.readValue +import com.github.tomakehurst.wiremock.WireMockServer +import org.hamcrest.MatcherAssert.assertThat +import org.hamcrest.Matchers.equalTo +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.test.web.servlet.MockMvc +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get +import org.springframework.test.web.servlet.result.MockMvcResultMatchers +import uk.gov.justice.digital.hmpps.data.generator.PersonGenerator +import uk.gov.justice.digital.hmpps.security.withOAuth2Token +import uk.gov.justice.digital.hmpps.service.Engagement +import uk.gov.justice.digital.hmpps.service.Identifiers +import uk.gov.justice.digital.hmpps.service.Name + +@AutoConfigureMockMvc +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +internal class EngagementCreatedTest { + @Autowired + internal lateinit var mockMvc: MockMvc + + @Autowired + internal lateinit var wireMockServer: WireMockServer + + @Autowired + internal lateinit var objectMapper: ObjectMapper + + @Test + fun `engagement details returned from detail url`() { + val person = PersonGenerator.ENGAGEMENT_CREATED + val response = mockMvc + .perform(get("/probation-case.engagement.created/${person.crn}").withOAuth2Token(wireMockServer)) + .andExpect(MockMvcResultMatchers.status().is2xxSuccessful).andReturn().response.contentAsString + + val engagement = objectMapper.readValue(response) + assertThat( + engagement, + equalTo( + Engagement( + Identifiers(person.crn, person.pnc), + Name(person.forename, person.surname, listOf()), + person.dateOfBirth + ) + ) + ) + } +} diff --git a/projects/domain-events-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/IntegrationTest.kt b/projects/domain-events-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/PublishingIntegrationTest.kt similarity index 54% rename from projects/domain-events-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/IntegrationTest.kt rename to projects/domain-events-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/PublishingIntegrationTest.kt index 6467c5d14d..8be37f6282 100644 --- a/projects/domain-events-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/IntegrationTest.kt +++ b/projects/domain-events-and-delius/src/integrationTest/kotlin/uk/gov/justice/digital/hmpps/PublishingIntegrationTest.kt @@ -1,5 +1,6 @@ package uk.gov.justice.digital.hmpps +import com.github.tomakehurst.wiremock.WireMockServer import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.Matchers.equalTo import org.junit.jupiter.api.Assertions.assertEquals @@ -14,11 +15,14 @@ import org.springframework.boot.test.context.SpringBootTest import org.springframework.boot.test.mock.mockito.MockBean import uk.gov.justice.digital.hmpps.data.generator.DomainEventGenerator import uk.gov.justice.digital.hmpps.integrations.delius.DomainEventRepository +import uk.gov.justice.digital.hmpps.message.HmppsDomainEvent +import uk.gov.justice.digital.hmpps.message.Notification import uk.gov.justice.digital.hmpps.messaging.HmppsChannelManager +import uk.gov.justice.digital.hmpps.service.enhancement.EnhancedEventType import uk.gov.justice.digital.hmpps.telemetry.TelemetryService @SpringBootTest -internal class IntegrationTest { +internal class PublishingIntegrationTest { @Value("\${messaging.producer.topic}") lateinit var topicName: String @@ -31,6 +35,9 @@ internal class IntegrationTest { @MockBean lateinit var telemetryService: TelemetryService + @Autowired + lateinit var wireMockServer: WireMockServer + @Test fun `messages are published successfully`() { domainEventRepository.saveAll( @@ -46,7 +53,31 @@ internal class IntegrationTest { topic.receive()?.eventType?.let { messages.add(it) } } - assertThat(messages.sorted(), equalTo(listOf("probation-case.registration.added", "probation-case.risk-scores.ogrs.manual-calculation"))) + assertThat( + messages.sorted(), + equalTo(listOf("probation-case.registration.added", "probation-case.risk-scores.ogrs.manual-calculation")) + ) + verify(telemetryService, timeout(30000)).trackEvent(eq("DomainEventsProcessed"), any(), any()) + assertEquals(0, domainEventRepository.count()) + } + + @Test + fun `engagement created messages include detail url`() { + domainEventRepository.save(DomainEventGenerator.generate(EnhancedEventType.ProbationCaseEngagementCreated.value)) + + val topic = hmppsChannelManager.getChannel(topicName) + val messages = mutableListOf>() + while (messages.size < 1) { + topic.receive()?.let { messages.add(it) } + } + + assertThat( + messages.first().eventType, + equalTo("probation-case.engagement.created") + ) + val domainEvent = messages.first().message as HmppsDomainEvent + assertThat(domainEvent.eventType, equalTo("probation-case.engagement.created")) + assertThat(domainEvent.detailUrl, equalTo("http://localhost:${wireMockServer.port()}/probation-case.engagement.created/X789654")) verify(telemetryService, timeout(30000)).trackEvent(eq("DomainEventsProcessed"), any(), any()) assertEquals(0, domainEventRepository.count()) } diff --git a/projects/domain-events-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/engagement/EngagementResource.kt b/projects/domain-events-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/engagement/EngagementResource.kt new file mode 100644 index 0000000000..91d3ea1a11 --- /dev/null +++ b/projects/domain-events-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/api/engagement/EngagementResource.kt @@ -0,0 +1,17 @@ +package uk.gov.justice.digital.hmpps.api.engagement + +import org.springframework.security.access.prepost.PreAuthorize +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PathVariable +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RestController +import uk.gov.justice.digital.hmpps.service.Engagement +import uk.gov.justice.digital.hmpps.service.PersonService + +@RestController +@RequestMapping +class EngagementResource(private val personService: PersonService) { + @PreAuthorize("hasRole('VIEW_PROBATION_CASE_ENGAGEMENT_CREATED')") + @GetMapping("probation-case.engagement.created/{crn}") + fun getEngagement(@PathVariable crn: String): Engagement = personService.findEngagement(crn) +} diff --git a/projects/domain-events-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/MessageAttribute.kt b/projects/domain-events-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/MessageAttribute.kt deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/projects/domain-events-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/person/entity/Person.kt b/projects/domain-events-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/person/entity/Person.kt new file mode 100644 index 0000000000..693921a72e --- /dev/null +++ b/projects/domain-events-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/integrations/delius/person/entity/Person.kt @@ -0,0 +1,49 @@ +package uk.gov.justice.digital.hmpps.integrations.delius.person.entity + +import jakarta.persistence.Column +import jakarta.persistence.Entity +import jakarta.persistence.Id +import jakarta.persistence.Table +import org.hibernate.annotations.Immutable +import org.hibernate.annotations.Where +import org.springframework.data.jpa.repository.JpaRepository +import java.time.LocalDate + +@Immutable +@Entity +@Table(name = "offender") +@Where(clause = "soft_deleted = 0") +class Person( + + @Column(columnDefinition = "char(7)") + val crn: String, + + @Column(name = "pnc_number", columnDefinition = "char(13)") + val pnc: String?, + + @Column(name = "first_name") + val forename: String, + + @Column(name = "second_name") + val secondName: String?, + + @Column(name = "third_name") + val thirdName: String?, + + @Column(name = "surname") + val surname: String, + + @Column(name = "date_of_birth_date") + val dateOfBirth: LocalDate, + + @Column(columnDefinition = "number") + val softDeleted: Boolean, + + @Id + @Column(name = "offender_id") + val id: Long +) + +interface PersonRepository : JpaRepository { + fun findByCrn(crn: String): Person? +} diff --git a/projects/domain-events-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/DomainEventService.kt b/projects/domain-events-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/DomainEventService.kt index 2cf196a6e5..be982e9dd2 100644 --- a/projects/domain-events-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/DomainEventService.kt +++ b/projects/domain-events-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/DomainEventService.kt @@ -11,6 +11,7 @@ import uk.gov.justice.digital.hmpps.integrations.delius.DomainEventRepository import uk.gov.justice.digital.hmpps.message.HmppsDomainEvent import uk.gov.justice.digital.hmpps.message.Notification import uk.gov.justice.digital.hmpps.publisher.NotificationPublisher +import uk.gov.justice.digital.hmpps.service.enhancement.NotificationEnhancer @Service class DomainEventService( @@ -18,12 +19,13 @@ class DomainEventService( private val batchSize: Int, private val objectMapper: ObjectMapper, private val domainEventRepository: DomainEventRepository, - private val notificationPublisher: NotificationPublisher + private val notificationPublisher: NotificationPublisher, + private val notificationEnhancer: NotificationEnhancer ) { @Transactional fun publishBatch(): Int { val deltas = domainEventRepository.findAll(Pageable.ofSize(batchSize)).content - val notifications = deltas.map { it.asNotification() } + val notifications = deltas.map { notificationEnhancer.enhance(it.asNotification()) } notifications.forEach { notificationPublisher.publish(it) } domainEventRepository.deleteAllByIdInBatch(deltas.map { it.id }) return deltas.size diff --git a/projects/domain-events-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/PersonService.kt b/projects/domain-events-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/PersonService.kt new file mode 100644 index 0000000000..9b3a87a302 --- /dev/null +++ b/projects/domain-events-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/PersonService.kt @@ -0,0 +1,33 @@ +package uk.gov.justice.digital.hmpps.service + +import org.springframework.stereotype.Service +import uk.gov.justice.digital.hmpps.exception.NotFoundException +import uk.gov.justice.digital.hmpps.integrations.delius.person.entity.Person +import uk.gov.justice.digital.hmpps.integrations.delius.person.entity.PersonRepository +import java.time.LocalDate + +@Service +class PersonService(private val personRepository: PersonRepository) { + fun findEngagement(crn: String): Engagement = personRepository.findByCrn(crn)?.asEngagement() + ?: throw NotFoundException("Engagement", "crn", crn) +} + +private fun Person.asEngagement() = Engagement( + Identifiers(crn, pnc), + Name(forename, surname, listOfNotNull(secondName, thirdName)), + dateOfBirth +) + +data class Engagement( + val identifiers: Identifiers, + val name: Name, + val dateOfBirth: LocalDate +) + +data class Identifiers(val crn: String, val pnc: String?) + +data class Name( + val forename: String, + val surname: String, + val otherNames: List +) diff --git a/projects/domain-events-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/enhancement/Enhancement.kt b/projects/domain-events-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/enhancement/Enhancement.kt new file mode 100644 index 0000000000..0a3934a8f3 --- /dev/null +++ b/projects/domain-events-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/enhancement/Enhancement.kt @@ -0,0 +1,27 @@ +package uk.gov.justice.digital.hmpps.service.enhancement + +import uk.gov.justice.digital.hmpps.message.HmppsDomainEvent +import uk.gov.justice.digital.hmpps.message.Notification + +interface Enhancement { + val eventType: EnhancedEventType + fun enhance(notification: Notification): Notification +} + +sealed interface EnhancedEventType { + val value: String + + data object ProbationCaseEngagementCreated : EnhancedEventType { + override val value = "probation-case.engagement.created" + } + + private data class NoEnhancement(override val value: String) : EnhancedEventType + + companion object { + private val types = listOf( + ProbationCaseEngagementCreated + ).associateBy { it.value } + + fun of(value: String): EnhancedEventType = types[value] ?: NoEnhancement(value) + } +} diff --git a/projects/domain-events-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/enhancement/NotificationEnhancer.kt b/projects/domain-events-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/enhancement/NotificationEnhancer.kt new file mode 100644 index 0000000000..68e81b4a99 --- /dev/null +++ b/projects/domain-events-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/enhancement/NotificationEnhancer.kt @@ -0,0 +1,19 @@ +package uk.gov.justice.digital.hmpps.service.enhancement + +import org.springframework.stereotype.Component +import uk.gov.justice.digital.hmpps.message.HmppsDomainEvent +import uk.gov.justice.digital.hmpps.message.Notification + +@Component +class NotificationEnhancer(enhancements: List) { + val enhancements = enhancements.associateBy { it.eventType } + + fun enhance(notification: Notification): Notification = + getEnhancement(EnhancedEventType.of(notification.message.eventType)).enhance(notification) + + private fun getEnhancement(enhancedEventType: EnhancedEventType): Enhancement = + enhancements[enhancedEventType] ?: object : Enhancement { + override val eventType = enhancedEventType + override fun enhance(notification: Notification) = notification + } +} diff --git a/projects/domain-events-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/enhancement/ProbationCaseEngagementCreatedEnhancement.kt b/projects/domain-events-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/enhancement/ProbationCaseEngagementCreatedEnhancement.kt new file mode 100644 index 0000000000..60f420df07 --- /dev/null +++ b/projects/domain-events-and-delius/src/main/kotlin/uk/gov/justice/digital/hmpps/service/enhancement/ProbationCaseEngagementCreatedEnhancement.kt @@ -0,0 +1,22 @@ +package uk.gov.justice.digital.hmpps.service.enhancement + +import org.springframework.beans.factory.annotation.Value +import org.springframework.stereotype.Component +import uk.gov.justice.digital.hmpps.message.HmppsDomainEvent +import uk.gov.justice.digital.hmpps.message.Notification + +@Component +class ProbationCaseEngagementCreatedEnhancement( + @Value("\${domain-events.base-url}") private val baseUrl: String +) : Enhancement { + override val eventType = EnhancedEventType.ProbationCaseEngagementCreated + + override fun enhance(notification: Notification): Notification { + val message = notification.message + return notification.copy( + message = message.copy( + detailUrl = "$baseUrl/${eventType.value}/${message.personReference.findCrn()}" + ) + ) + } +} diff --git a/projects/domain-events-and-delius/src/main/resources/application.yml b/projects/domain-events-and-delius/src/main/resources/application.yml index 5dbc718c85..7c580fcb86 100644 --- a/projects/domain-events-and-delius/src/main/resources/application.yml +++ b/projects/domain-events-and-delius/src/main/resources/application.yml @@ -16,6 +16,8 @@ spring: global_temporary: create_tables: false drop_tables: false +springdoc.default-produces-media-type: application/json + delius.db.username: DomainEventsAndDelius # Should match value in [deploy/database/access.yml]. @@ -31,6 +33,7 @@ spring.config.activate.on-profile: [ "dev", "integration-test" ] spring: datasource.url: jdbc:h2:file:./dev;MODE=Oracle;DEFAULT_NULL_ORDERING=HIGH;AUTO_SERVER=true;AUTO_SERVER_PORT=9092 jpa.hibernate.ddl-auto: create-drop + security.oauth2.resourceserver.jwt.public-key-location: classpath:local-public-key.pub seed.database: true @@ -38,6 +41,11 @@ poller.fixed-delay: 2000 messaging.producer.topic: domain-events +context.initializer.classes: uk.gov.justice.digital.hmpps.wiremock.WireMockInitialiser + +domain-events: + base-url: http://localhost:${wiremock.port} + logging.level: uk.gov.justice.digital.hmpps: DEBUG org.hibernate.tool.schema: ERROR diff --git a/projects/domain-events-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/service/DomainEventServiceTest.kt b/projects/domain-events-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/service/DomainEventServiceTest.kt index bd3e19d47f..8ec9db32bf 100644 --- a/projects/domain-events-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/service/DomainEventServiceTest.kt +++ b/projects/domain-events-and-delius/src/test/kotlin/uk/gov/justice/digital/hmpps/service/DomainEventServiceTest.kt @@ -21,6 +21,7 @@ import org.springframework.data.domain.Pageable import uk.gov.justice.digital.hmpps.data.generator.DomainEventGenerator import uk.gov.justice.digital.hmpps.integrations.delius.DomainEventRepository import uk.gov.justice.digital.hmpps.publisher.NotificationPublisher +import uk.gov.justice.digital.hmpps.service.enhancement.NotificationEnhancer @ExtendWith(MockitoExtension::class) class DomainEventServiceTest { @@ -31,6 +32,9 @@ class DomainEventServiceTest { @Mock private lateinit var notificationPublisher: NotificationPublisher + @Mock + private lateinit var notificationEnhancer: NotificationEnhancer + private lateinit var service: DomainEventService @BeforeEach @@ -39,8 +43,10 @@ class DomainEventServiceTest { batchSize = 50, objectMapper = jacksonObjectMapper().findAndRegisterModules(), domainEventRepository = domainEventRepository, - notificationPublisher = notificationPublisher + notificationPublisher = notificationPublisher, + notificationEnhancer = notificationEnhancer ) + whenever(notificationEnhancer.enhance(any())).thenAnswer { it.getArgument(0) } } @Test