Repository: hmrc/alcohol-duty-contact-preferences
Pull request #4: ADR 1617 - ECP backend route for event hub integration
Author: login: simondrugan16
Created: 2025-03-04T10:47:49Z | Merged: 2025-03-10T16:37:29Z

For the ticket: [ADR-1617](https://jira.tools.tax.service.gov.uk/browse/ADR-1617) ECP [DEV]: Register Interest ADREPC with Event Hub service (con fig), I created a test only route in the ECP backend for us to recepive the POST requests rent out by event hub. This is more of a proof of concept. When the ECP Frontend develops more, this will link up to ETMP, and we will tell them that the email has bounced. For now we just log success/failure and return an appropriote response.


Diff:
diff --git a/README.md b/README.md
index 66f9956..189175e 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,70 @@
-
 # alcohol-duty-contact-preferences
 
 This is the backend service to capture an alcohol producers communication preference
 
+## Test only endpoints
+
+### Event hub bounced email endpoint
+
+This is a test only endpoint used for checking that we can successfully integrate with Event Hub in the local environment.
+In future, this endpoint will be used by Event Hub in the instance that an email sent out has bounced. When this happens
+we will tell ETMP that this has happened. At the moment this functionality has not been implemented, but will be during
+the development of the ECP microservice.
+
+The endpoint route is:
+> `POST /event-hub/bounce`
+
+For it to work you need this service running with test only routes enabled:
+> `sbt "run -Dapplication.router=testOnlyDoNotUseInAppConf.Routes"`
+
+and all the event hub running service manager with the correct config. This can be added alongside all ADR microservices
+via:
+> `sm2 --start ALCOHOL_DUTY_ALL`
+
+or independently with:
+> `sm2 --start EVENT_HUB_FOR_ADR`
+
+An example request, via an API client like Bruno, to Event Hub, to hit this endpoint is:
+
+```
+curl -v -X POST -H "Content-Type: application/json" http://localhost:9050/event-hub/publish/email -d '
+{
+    "eventId": "623b6f96-d36f-4014-8874-7f3f8287f9e6", 
+    "subject": "calling", 
+    "groupId": "su users",
+    "timestamp": "2021-07-01T13:09:29Z",
+    "event" : {
+        "event": "failed",
+        "emailAddress": "hmrc-customer@some-domain.org",
+        "detected": "2021-04-07T09:46:29+00:00",
+        "code": 605,
+        "reason": "Not delivering to previously bounced address",
+        "enrolment": "HMRC-AD-ORG~APPAID~XMADP0000100208"
+    }
+}'
+```
+
+to hit this endpoint directly, without going through event hub you can use this request:
+
+```
+curl -v -X POST -H "Content-Type: application/json" http://localhost:16006/alcohol-duty-contact-preferences/test-only/event-hub/bounce -d '
+{
+    "eventId": "550e8400-e29b-41d4-a716-446655440000",
+    "subject": "testSubject",
+    "groupId": "testGroupId",
+    "timestamp": "2021-07-01T13:09:29",
+    "event": {
+        "event":"failed",
+        "emailAddress":"hmrc-customer@some-domain.org",
+        "detected":"2021-04-07T09:46:29+00:00",
+        "code":605,
+        "reason":"Not delivering to previously bounced address",
+        "enrolment":"HMRC-AD-ORG~APPAID~XMADP0000100208"
+    }
+}'
+```
+
 ### License
 
-This code is open source software licensed under the [Apache 2.0 License]("http://www.apache.org/licenses/LICENSE-2.0.html").
\ No newline at end of file
+This code is open source software licensed under
+the [Apache 2.0 License]("http://www.apache.org/licenses/LICENSE-2.0.html").
\ No newline at end of file
diff --git a/app/uk/gov/hmrc/alcoholdutycontactpreferences/testOnly/controllers/EventHubBounceController.scala b/app/uk/gov/hmrc/alcoholdutycontactpreferences/testOnly/controllers/EventHubBounceController.scala
new file mode 100644
index 0000000..6f9861b
--- /dev/null
+++ b/app/uk/gov/hmrc/alcoholdutycontactpreferences/testOnly/controllers/EventHubBounceController.scala
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2025 HM Revenue & Customs
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package uk.gov.hmrc.alcoholdutycontactpreferences.testOnly.controllers
+
+import play.api.Logging
+import play.api.libs.json.JsValue
+import play.api.mvc.{Action, BaseController, ControllerComponents}
+import uk.gov.hmrc.alcoholdutycontactpreferences.testOnly.models.Event
+
+import javax.inject.Inject
+import scala.concurrent.Future
+
+class EventHubBounceController @Inject() (val controllerComponents: ControllerComponents)
+    extends BaseController
+    with Logging {
+
+  def handleBouncedEmail(): Action[JsValue] = Action.async(parse.json) { implicit request =>
+    request.body
+      .validate[Event]
+      .fold(
+        invalid = error => {
+          logger.warn(s"Bounced email json body could not be parsed as Event. Error: $error")
+          Future.successful(InternalServerError("Bounced email json body could not be parsed as Event"))
+        },
+        valid = event => {
+          logger.info(
+            s"Bounced email received successfully. eventId: ${event.eventId}," +
+              s" subject: ${event.subject}, groupId: ${event.groupId}, timestamp: ${event.timestamp}, event: ${event.event}"
+          )
+          Future.successful(Ok("Bounced email received successfully"))
+        }
+      )
+  }
+
+}
diff --git a/app/uk/gov/hmrc/alcoholdutycontactpreferences/testOnly/models/Event.scala b/app/uk/gov/hmrc/alcoholdutycontactpreferences/testOnly/models/Event.scala
new file mode 100644
index 0000000..50acc0d
--- /dev/null
+++ b/app/uk/gov/hmrc/alcoholdutycontactpreferences/testOnly/models/Event.scala
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2025 HM Revenue & Customs
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package uk.gov.hmrc.alcoholdutycontactpreferences.testOnly.models
+
+import play.api.libs.functional.syntax.toFunctionalBuilderOps
+import play.api.libs.json.Reads.verifying
+import play.api.libs.json._
+
+import java.time.LocalDateTime
+import java.util.UUID
+
+final case class Event(eventId: UUID, subject: String, groupId: String, timestamp: LocalDateTime, event: JsValue)
+
+object Event {
+
+  implicit val requestDetailReads: Reads[Event] = (
+    (JsPath \ "eventId").read[UUID] and
+      (JsPath \ "subject").read[String](verifying[String](a => a.trim.nonEmpty)) and
+      (JsPath \ "groupId").read[String] and
+      (JsPath \ "timestamp").read[LocalDateTime] and
+      (JsPath \ "event").read[JsValue]
+  )(Event.apply _)
+
+  implicit val eventWrites: Writes[Event] = Json.writes[Event]
+
+}
diff --git a/conf/app.routes b/conf/app.routes
index d91e33e..e1e4a6a 100755
--- a/conf/app.routes
+++ b/conf/app.routes
@@ -1,2 +1,3 @@
 # microservice specific routes
 
+
diff --git a/conf/test.routes b/conf/test.routes
new file mode 100755
index 0000000..1583b52
--- /dev/null
+++ b/conf/test.routes
@@ -0,0 +1,4 @@
+# Add all the application routes to the app.routes file
+
+POST         /event-hub/bounce                   uk.gov.hmrc.alcoholdutycontactpreferences.testOnly.controllers.EventHubBounceController.handleBouncedEmail()
+
diff --git a/conf/testOnlyDoNotUseInAppConf.routes b/conf/testOnlyDoNotUseInAppConf.routes
index 71a2d0e..32c37e9 100755
--- a/conf/testOnlyDoNotUseInAppConf.routes
+++ b/conf/testOnlyDoNotUseInAppConf.routes
@@ -10,4 +10,7 @@
 # Failing to follow this rule may result in test routes deployed in production.
 
 # Add all the application routes to the prod.routes file
-->         /                          prod.Routes
+
+->        /                                             prod.Routes
+->        /alcohol-duty-contact-preferences/test-only/  test.Routes
+


Reviews:
user: login: ajchilts
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-05T11:55:02Z
user: login: ajchilts
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-05T13:25:56Z
user: login: ajchilts
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-06T10:09:14Z
user: login: ajchilts
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-06T11:28:58Z

Review comments:
diff_hunk: @@ -0,0 +1,49 @@
+/*
+ * Copyright 2025 HM Revenue & Customs
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package uk.gov.hmrc.alcoholdutycontactpreferences.testOnly.controllers
+
+import play.api.Logging
+import play.api.libs.json.JsValue
+import play.api.mvc.{Action, BaseController, ControllerComponents}
+import uk.gov.hmrc.alcoholdutycontactpreferences.testOnly.models.Event
+
+import javax.inject.Inject
+import scala.concurrent.Future
+
+class EventHubBounceController @Inject() (val controllerComponents: ControllerComponents)
+    extends BaseController
+    with Logging {
+
+  def handleBouncedEmail(): Action[JsValue] = Action.async(parse.json) { implicit request =>
path: app/uk/gov/hmrc/alcoholdutycontactpreferences/testOnly/controllers/EventHubBounceController.scala
user: login: ajchilts
body: Do we need some kind of basic auth @simondrugan16 ? 
created_at: 2025-03-05T11:54:42Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,49 @@
+/*
+ * Copyright 2025 HM Revenue & Customs
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package uk.gov.hmrc.alcoholdutycontactpreferences.testOnly.controllers
+
+import play.api.Logging
+import play.api.libs.json.JsValue
+import play.api.mvc.{Action, BaseController, ControllerComponents}
+import uk.gov.hmrc.alcoholdutycontactpreferences.testOnly.models.Event
+
+import javax.inject.Inject
+import scala.concurrent.Future
+
+class EventHubBounceController @Inject() (val controllerComponents: ControllerComponents)
+    extends BaseController
+    with Logging {
+
+  def handleBouncedEmail(): Action[JsValue] = Action.async(parse.json) { implicit request =>
path: app/uk/gov/hmrc/alcoholdutycontactpreferences/testOnly/controllers/EventHubBounceController.scala
user: login: ajchilts
body: @simondrugan16  - This is the direct debit implementation of the very same journey we are looking to implement. 
https://github.com/hmrc/direct-debit-backend/blob/main/app/controllers/BouncedEmailController.scala#L26 

As long as we align with this I think we will be good. 
created_at: 2025-03-05T13:25:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,8 +1,70 @@
-
 # alcohol-duty-contact-preferences
 
 This is the backend service to capture an alcohol producers communication preference
 
+## Test only endpoints
+
+### Event hub bounced email endpoint
+
+This is a test only endpoint used for checking that we can successfully integrate with Event Hub in the local environment.
+In future, this endpoint will be used by Event Hub in the instance that an email sent out has bounced. When this happens
+we will tell ETMP that this has happened. At the moment this functionality has not been implemented, but will be during
+the development of the ECP microservice.
+
+The endpoint route is:
+> `POST /event-hub/bounce`
+
+For it to work you need this service running with test only routes enabled:
+> `sbt "run -Dapplication.router=testOnlyDoNotUseInAppConf.Routes"`
+
+and all the event hub running service manager with the correct config. This can be added alongside all ADR microservices
+via:
+> `sm2 --start ALCOHOL_DUTY_ALL`
+
+or independently with:
+> `sm2 --start EVENT_HUB_FOR_ADR`
+
+An example request, via an API client like Bruno, to Event Hub, to hit this endpoint is:
+
+```
+curl -v -X POST -H "Content-Type: application/json" http://localhost:9050/event-hub/publish/email -d '
+{
+    "eventId": "623b6f96-d36f-4014-8874-7f3f8287f9e6", 
+    "subject": "calling", 
+    "groupId": "su users",
+    "timestamp": "2021-07-01T13:09:29Z",
+    "event" : {
+        "event": "failed",
+        "emailAddress": "hmrc-customer@some-domain.org",
+        "detected": "2021-04-07T09:46:29+00:00",
+        "code": 605,
+        "reason": "Not delivering to previously bounced address",
+        "enrolment": "HMRC-CUS-ORG~EORINumber~GB123456789"
path: README.md
user: login: ajchilts
body: @simondrugan16  - I think we should change this to be the ADR enrolment? Might get forgotten. 
created_at: 2025-03-06T09:49:05Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,8 +1,70 @@
-
 # alcohol-duty-contact-preferences
 
 This is the backend service to capture an alcohol producers communication preference
 
+## Test only endpoints
+
+### Event hub bounced email endpoint
+
+This is a test only endpoint used for checking that we can successfully integrate with Event Hub in the local environment.
+In future, this endpoint will be used by Event Hub in the instance that an email sent out has bounced. When this happens
+we will tell ETMP that this has happened. At the moment this functionality has not been implemented, but will be during
+the development of the ECP microservice.
+
+The endpoint route is:
+> `POST /event-hub/bounce`
+
+For it to work you need this service running with test only routes enabled:
+> `sbt "run -Dapplication.router=testOnlyDoNotUseInAppConf.Routes"`
+
+and all the event hub running service manager with the correct config. This can be added alongside all ADR microservices
+via:
+> `sm2 --start ALCOHOL_DUTY_ALL`
+
+or independently with:
+> `sm2 --start EVENT_HUB_FOR_ADR`
+
+An example request, via an API client like Bruno, to Event Hub, to hit this endpoint is:
+
+```
+curl -v -X POST -H "Content-Type: application/json" http://localhost:9050/event-hub/publish/email -d '
+{
+    "eventId": "623b6f96-d36f-4014-8874-7f3f8287f9e6", 
+    "subject": "calling", 
+    "groupId": "su users",
+    "timestamp": "2021-07-01T13:09:29Z",
+    "event" : {
+        "event": "failed",
+        "emailAddress": "hmrc-customer@some-domain.org",
+        "detected": "2021-04-07T09:46:29+00:00",
+        "code": 605,
+        "reason": "Not delivering to previously bounced address",
+        "enrolment": "HMRC-CUS-ORG~EORINumber~GB123456789"
+    }
+}'
+```
+
+to hit this endpoint directly, without going through event hub you can use this request:
+
+```
+curl -v -X POST -H "Content-Type: application/json" http://localhost:16006/alcohol-duty-contact-preferences/test-only/event-hub/bounce -d '
+{
+    "eventId": "550e8400-e29b-41d4-a716-446655440000",
+    "subject": "testSubject",
+    "groupId": "testGroupId",
+    "timestamp": "2021-07-01T13:09:29",
+    "event": {
+        "event":"failed",
+        "emailAddress":"hmrc-customer@some-domain.org",
+        "detected":"2021-04-07T09:46:29+00:00",
+        "code":605,
+        "reason":"Not delivering to previously bounced address",
+        "enrolment":"HMRC-CUS-ORG~EORINumber~GB123456789"
path: README.md
user: login: ajchilts
body: AS above. Change this to be the ADR enrolment? 
created_at: 2025-03-06T09:49:29Z
author_association: CONTRIBUTOR

PR comments:
user: login: platops-pr-bot
created_at: 2025-03-04T10:54:27Z
body: - `uk.gov.hmrc.sbt-auto-build` can be updated to `3.24.0` in [project/plugins.sbt](https://github.com/hmrc/alcohol-duty-contact-preferences/blob/ADR-1617/project/plugins.sbt#L5)
- `uk.gov.hmrc.sbt-distributables` can be updated to `2.6.0` in [project/plugins.sbt](https://github.com/hmrc/alcohol-duty-contact-preferences/blob/ADR-1617/project/plugins.sbt#L6)
- Your service can now use Java 21. Please set `JavaType.OPENJDK_JRE21` in [build-jobs](https://github.com/hmrc/build-jobs/blob/HEAD/jobs/live/alcoholDuty.groovy#L65) - See confluence https://confluence.tools.tax.service.gov.uk/x/xIACM
- There is a bobby warning (builds will be prevented after 14 Jul 2025) - see the pr builder for details
author_association: NONE
user: login: ajchilts
created_at: 2025-03-05T11:51:42Z
body: @simondrugan16  - Can we please add something to the readme that talks about how to test this? I.e. run the SM profile and provide an example curl request? 
author_association: CONTRIBUTOR
user: login: platops-pr-bot
created_at: 2025-03-05T17:46:16Z
body: - `uk.gov.hmrc.sbt-auto-build` can be updated to `3.24.0` in [project/plugins.sbt](https://github.com/hmrc/alcohol-duty-contact-preferences/blob/ADR-1617/project/plugins.sbt#L5)
- `uk.gov.hmrc.sbt-distributables` can be updated to `2.6.0` in [project/plugins.sbt](https://github.com/hmrc/alcohol-duty-contact-preferences/blob/ADR-1617/project/plugins.sbt#L6)
- uk.gov.hmrc:bootstrap-backend-play-30 can be updated from 9.5.0 to 9.9.0 in [project/AppDependencies.scala](https://github.com/hmrc/alcohol-duty-contact-preferences/blob/ADR-1617/project/AppDependencies.scala#L1).
- uk.gov.hmrc.mongo:hmrc-mongo-play-30 can be updated from 2.3.0 to 2.5.0 in [project/AppDependencies.scala](https://github.com/hmrc/alcohol-duty-contact-preferences/blob/ADR-1617/project/AppDependencies.scala#L1).
- uk.gov.hmrc:bootstrap-test-play-30 can be updated from 9.5.0 to 9.9.0 in [project/AppDependencies.scala](https://github.com/hmrc/alcohol-duty-contact-preferences/blob/ADR-1617/project/AppDependencies.scala#L1).
- uk.gov.hmrc.mongo:hmrc-mongo-test-play-30 can be updated from 2.3.0 to 2.5.0 in [project/AppDependencies.scala](https://github.com/hmrc/alcohol-duty-contact-preferences/blob/ADR-1617/project/AppDependencies.scala#L1).
- Your service can now use Java 21. Please set `JavaType.OPENJDK_JRE21` in [build-jobs](https://github.com/hmrc/build-jobs/blob/HEAD/jobs/live/alcoholDuty.groovy#L65) - See confluence https://confluence.tools.tax.service.gov.uk/x/xIACM
- There is a bobby warning (builds will be prevented after 14 Jul 2025) - see the pr builder for details
author_association: NONE
user: login: platops-pr-bot
created_at: 2025-03-06T11:28:20Z
body: - ~~uk.gov.hmrc:bootstrap-backend-play-30 can be updated from 9.5.0 to 9.9.0 in [project/AppDependencies.scala](https://github.com/hmrc/alcohol-duty-contact-preferences/blob/ADR-1617/project/AppDependencies.scala#L1).~~
- ~~uk.gov.hmrc:bootstrap-test-play-30 can be updated from 9.5.0 to 9.9.0 in [project/AppDependencies.scala](https://github.com/hmrc/alcohol-duty-contact-preferences/blob/ADR-1617/project/AppDependencies.scala#L1).~~
- `uk.gov.hmrc.sbt-auto-build` can be updated to `3.24.0` in [project/plugins.sbt](https://github.com/hmrc/alcohol-duty-contact-preferences/blob/ADR-1617/project/plugins.sbt#L5)
- `uk.gov.hmrc.sbt-distributables` can be updated to `2.6.0` in [project/plugins.sbt](https://github.com/hmrc/alcohol-duty-contact-preferences/blob/ADR-1617/project/plugins.sbt#L6)
- uk.gov.hmrc:bootstrap-backend-play-30 can be updated from 9.5.0 to 9.10.0 in [project/AppDependencies.scala](https://github.com/hmrc/alcohol-duty-contact-preferences/blob/ADR-1617/project/AppDependencies.scala#L1).
- uk.gov.hmrc.mongo:hmrc-mongo-play-30 can be updated from 2.3.0 to 2.5.0 in [project/AppDependencies.scala](https://github.com/hmrc/alcohol-duty-contact-preferences/blob/ADR-1617/project/AppDependencies.scala#L1).
- uk.gov.hmrc:bootstrap-test-play-30 can be updated from 9.5.0 to 9.10.0 in [project/AppDependencies.scala](https://github.com/hmrc/alcohol-duty-contact-preferences/blob/ADR-1617/project/AppDependencies.scala#L1).
- uk.gov.hmrc.mongo:hmrc-mongo-test-play-30 can be updated from 2.3.0 to 2.5.0 in [project/AppDependencies.scala](https://github.com/hmrc/alcohol-duty-contact-preferences/blob/ADR-1617/project/AppDependencies.scala#L1).
- Your service can now use Java 21. Please set `JavaType.OPENJDK_JRE21` in [build-jobs](https://github.com/hmrc/build-jobs/blob/HEAD/jobs/live/alcoholDuty.groovy#L65) - See confluence https://confluence.tools.tax.service.gov.uk/x/xIACM
- There is a bobby warning (builds will be prevented after 14 Jul 2025) - see the pr builder for details
author_association: NONE