From b44ae4f8f593e4f8da6d41757944d23d150e588f Mon Sep 17 00:00:00 2001
From: Michael Wolfendale <4563722+wolfendale@users.noreply.github.com>
Date: Wed, 25 Sep 2024 16:01:55 +0100
Subject: [PATCH 1/2] Add queries for counting / retrieving miscoded movements
---
.../models/messages/IE704Message.scala | 2 +-
.../models/messages/IE801Message.scala | 2 +-
.../models/messages/IE802Message.scala | 2 +-
.../models/messages/IE803Message.scala | 2 +-
.../models/messages/IE807Message.scala | 2 +-
.../models/messages/IE813Message.scala | 2 +-
.../models/messages/IE815Message.scala | 2 +-
.../models/messages/IE818Message.scala | 2 +-
.../models/messages/IE819Message.scala | 2 +-
.../models/messages/IE829Message.scala | 2 +-
.../models/messages/IE837Message.scala | 2 +-
.../models/messages/IE839Message.scala | 2 +-
.../models/messages/IE840Message.scala | 2 +-
.../models/messages/IE871Message.scala | 2 +-
.../models/messages/IE881Message.scala | 2 +-
.../repository/MovementRepository.scala | 26 +++-
.../repository/model/MiscodedMovement.scala | 26 ++++
.../repository/MovementRepositoryItSpec.scala | 141 +++++++++++++++++-
18 files changed, 203 insertions(+), 20 deletions(-)
create mode 100644 app/uk/gov/hmrc/excisemovementcontrolsystemapi/repository/model/MiscodedMovement.scala
diff --git a/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE704Message.scala b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE704Message.scala
index a8ac526a..9b013c8e 100644
--- a/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE704Message.scala
+++ b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE704Message.scala
@@ -27,7 +27,7 @@ import uk.gov.hmrc.excisemovementcontrolsystemapi.models.messages.MessageTypeFor
import scala.xml.NodeSeq
case class IE704Message(
- private val obj: IE704Type,
+ obj: IE704Type,
key: Option[String],
namespace: Option[String],
auditType: AuditType
diff --git a/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE801Message.scala b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE801Message.scala
index 1dd0a2b5..3d8e0654 100644
--- a/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE801Message.scala
+++ b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE801Message.scala
@@ -27,7 +27,7 @@ import uk.gov.hmrc.excisemovementcontrolsystemapi.models.messages.MessageTypeFor
import scala.xml.NodeSeq
case class IE801Message(
- private val obj: IE801Type,
+ obj: IE801Type,
key: Option[String],
namespace: Option[String],
auditType: AuditType
diff --git a/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE802Message.scala b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE802Message.scala
index 07501c8d..a1d9b84d 100644
--- a/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE802Message.scala
+++ b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE802Message.scala
@@ -27,7 +27,7 @@ import uk.gov.hmrc.excisemovementcontrolsystemapi.models.messages.MessageTypeFor
import scala.xml.NodeSeq
case class IE802Message(
- private val obj: IE802Type,
+ obj: IE802Type,
key: Option[String],
namespace: Option[String],
auditType: AuditType
diff --git a/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE803Message.scala b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE803Message.scala
index 60584f2e..a2738c9c 100644
--- a/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE803Message.scala
+++ b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE803Message.scala
@@ -27,7 +27,7 @@ import uk.gov.hmrc.excisemovementcontrolsystemapi.models.messages.MessageTypeFor
import scala.xml.NodeSeq
case class IE803Message(
- private val obj: IE803Type,
+ obj: IE803Type,
key: Option[String],
namespace: Option[String],
auditType: AuditType
diff --git a/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE807Message.scala b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE807Message.scala
index fba99d5c..83e9801f 100644
--- a/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE807Message.scala
+++ b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE807Message.scala
@@ -27,7 +27,7 @@ import uk.gov.hmrc.excisemovementcontrolsystemapi.models.messages.MessageTypeFor
import scala.xml.NodeSeq
case class IE807Message(
- private val obj: IE807Type,
+ obj: IE807Type,
key: Option[String],
namespace: Option[String],
auditType: AuditType
diff --git a/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE813Message.scala b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE813Message.scala
index 6717cf48..82eccc6a 100644
--- a/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE813Message.scala
+++ b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE813Message.scala
@@ -27,7 +27,7 @@ import uk.gov.hmrc.excisemovementcontrolsystemapi.models.messages.MessageTypeFor
import scala.xml.NodeSeq
case class IE813Message(
- private val obj: IE813Type,
+ obj: IE813Type,
key: Option[String],
namespace: Option[String],
auditType: AuditType
diff --git a/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE815Message.scala b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE815Message.scala
index 26385d92..96fba747 100644
--- a/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE815Message.scala
+++ b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE815Message.scala
@@ -25,7 +25,7 @@ import uk.gov.hmrc.excisemovementcontrolsystemapi.models.messages.MessageTypeFor
import scala.xml.NodeSeq
-case class IE815Message(private val obj: IE815Type, auditType: AuditType) extends IEMessage with GeneratedJsonWriters {
+case class IE815Message(obj: IE815Type, auditType: AuditType) extends IEMessage with GeneratedJsonWriters {
def localReferenceNumber: String =
obj.Body.SubmittedDraftOfEADESAD.EadEsadDraft.LocalReferenceNumber
diff --git a/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE818Message.scala b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE818Message.scala
index 71ff2d82..15f18a15 100644
--- a/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE818Message.scala
+++ b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE818Message.scala
@@ -27,7 +27,7 @@ import uk.gov.hmrc.excisemovementcontrolsystemapi.models.messages.MessageTypeFor
import scala.xml.NodeSeq
case class IE818Message(
- private val obj: IE818Type,
+ obj: IE818Type,
key: Option[String],
namespace: Option[String],
auditType: AuditType
diff --git a/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE819Message.scala b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE819Message.scala
index 58bc7d04..5db8f954 100644
--- a/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE819Message.scala
+++ b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE819Message.scala
@@ -27,7 +27,7 @@ import uk.gov.hmrc.excisemovementcontrolsystemapi.models.messages.MessageTypeFor
import scala.xml.NodeSeq
case class IE819Message(
- private val obj: IE819Type,
+ obj: IE819Type,
key: Option[String],
namespace: Option[String],
auditType: AuditType
diff --git a/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE829Message.scala b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE829Message.scala
index 930ea018..90d061e3 100644
--- a/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE829Message.scala
+++ b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE829Message.scala
@@ -27,7 +27,7 @@ import uk.gov.hmrc.excisemovementcontrolsystemapi.models.messages.MessageTypeFor
import scala.xml.NodeSeq
case class IE829Message(
- private val obj: IE829Type,
+ obj: IE829Type,
key: Option[String],
namespace: Option[String],
auditType: AuditType
diff --git a/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE837Message.scala b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE837Message.scala
index 247c1f5c..1be1c7c9 100644
--- a/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE837Message.scala
+++ b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE837Message.scala
@@ -27,7 +27,7 @@ import uk.gov.hmrc.excisemovementcontrolsystemapi.models.messages.MessageTypeFor
import scala.xml.NodeSeq
case class IE837Message(
- private val obj: IE837Type,
+ obj: IE837Type,
key: Option[String],
namespace: Option[String],
auditType: AuditType
diff --git a/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE839Message.scala b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE839Message.scala
index 65fc720e..f576fa88 100644
--- a/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE839Message.scala
+++ b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE839Message.scala
@@ -27,7 +27,7 @@ import uk.gov.hmrc.excisemovementcontrolsystemapi.models.messages.MessageTypeFor
import scala.xml.NodeSeq
case class IE839Message(
- private val obj: IE839Type,
+ obj: IE839Type,
key: Option[String],
namespace: Option[String],
auditType: AuditType
diff --git a/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE840Message.scala b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE840Message.scala
index 7e7f9220..c457eef0 100644
--- a/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE840Message.scala
+++ b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE840Message.scala
@@ -27,7 +27,7 @@ import uk.gov.hmrc.excisemovementcontrolsystemapi.models.messages.MessageTypeFor
import scala.xml.NodeSeq
case class IE840Message(
- private val obj: IE840Type,
+ obj: IE840Type,
key: Option[String],
namespace: Option[String],
auditType: AuditType
diff --git a/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE871Message.scala b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE871Message.scala
index 2128a836..847baae2 100644
--- a/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE871Message.scala
+++ b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE871Message.scala
@@ -27,7 +27,7 @@ import uk.gov.hmrc.excisemovementcontrolsystemapi.models.messages.MessageTypeFor
import scala.xml.NodeSeq
case class IE871Message(
- private val obj: IE871Type,
+ obj: IE871Type,
key: Option[String],
namespace: Option[String],
auditType: AuditType
diff --git a/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE881Message.scala b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE881Message.scala
index 516ed1c7..c3416684 100644
--- a/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE881Message.scala
+++ b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE881Message.scala
@@ -27,7 +27,7 @@ import uk.gov.hmrc.excisemovementcontrolsystemapi.models.messages.MessageTypeFor
import scala.xml.NodeSeq
case class IE881Message(
- private val obj: IE881Type,
+ obj: IE881Type,
key: Option[String],
namespace: Option[String],
auditType: AuditType
diff --git a/app/uk/gov/hmrc/excisemovementcontrolsystemapi/repository/MovementRepository.scala b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/repository/MovementRepository.scala
index 32a892bd..b0a8ad1e 100644
--- a/app/uk/gov/hmrc/excisemovementcontrolsystemapi/repository/MovementRepository.scala
+++ b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/repository/MovementRepository.scala
@@ -25,7 +25,7 @@ import play.api.libs.json.{JsObject, Json, OFormat}
import uk.gov.hmrc.excisemovementcontrolsystemapi.config.AppConfig
import uk.gov.hmrc.excisemovementcontrolsystemapi.filters.MovementFilter
import uk.gov.hmrc.excisemovementcontrolsystemapi.repository.MovementRepository._
-import uk.gov.hmrc.excisemovementcontrolsystemapi.repository.model.{Movement, ProblemMovement, Total}
+import uk.gov.hmrc.excisemovementcontrolsystemapi.repository.model.{MiscodedMovement, Movement, ProblemMovement, Total}
import uk.gov.hmrc.excisemovementcontrolsystemapi.utils.{DateTimeService, Mdc}
import uk.gov.hmrc.mongo.MongoComponent
import uk.gov.hmrc.mongo.play.json.Codecs.JsonOps
@@ -54,7 +54,8 @@ class MovementRepository @Inject() (
Codecs.playFormatCodec(ErnAndLastReceived.format),
Codecs.playFormatCodec(MessageNotification.format),
Codecs.playFormatCodec(ProblemMovement.format),
- Codecs.playFormatCodec(Total.format)
+ Codecs.playFormatCodec(Total.format),
+ Codecs.playFormatCodec(MiscodedMovement.format)
),
replaceIndexes = false
) {
@@ -312,6 +313,27 @@ class MovementRepository @Inject() (
)
)
.headOption()
+
+ def getMiscodedMovements(): Future[Seq[MiscodedMovement]] =
+ collection
+ .find[MiscodedMovement](
+ Filters.and(
+ Filters.exists("messages.recipient", exists = true),
+ Filters.regex("messages.encodedMessage", "^PElFODAxVHlwZS")
+ )
+ )
+ .projection(Projections.fields(Projections.include("_id")))
+ .toFuture()
+
+ def getCountOfMiscodedMovements(): Future[Long] =
+ collection
+ .countDocuments(
+ Filters.and(
+ Filters.exists("messages.recipient", exists = true),
+ Filters.regex("messages.encodedMessage", "^PElFODAxVHlwZS")
+ )
+ )
+ .toFuture()
}
object MovementRepository {
diff --git a/app/uk/gov/hmrc/excisemovementcontrolsystemapi/repository/model/MiscodedMovement.scala b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/repository/model/MiscodedMovement.scala
new file mode 100644
index 00000000..74af5c15
--- /dev/null
+++ b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/repository/model/MiscodedMovement.scala
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2024 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.excisemovementcontrolsystemapi.repository.model
+
+import play.api.libs.json.{Json, OFormat}
+
+final case class MiscodedMovement(_id: String)
+
+object MiscodedMovement {
+
+ implicit lazy val format: OFormat[MiscodedMovement] = Json.format
+}
diff --git a/it/test/uk/gov/hmrc/excisemovementcontrolsystemapi/repository/MovementRepositoryItSpec.scala b/it/test/uk/gov/hmrc/excisemovementcontrolsystemapi/repository/MovementRepositoryItSpec.scala
index 410d5340..d40824df 100644
--- a/it/test/uk/gov/hmrc/excisemovementcontrolsystemapi/repository/MovementRepositoryItSpec.scala
+++ b/it/test/uk/gov/hmrc/excisemovementcontrolsystemapi/repository/MovementRepositoryItSpec.scala
@@ -16,6 +16,7 @@
package uk.gov.hmrc.excisemovementcontrolsystemapi.repository
+import generated.IE801Type
import org.mockito.MockitoSugar.when
import org.mongodb.scala.model.Filters
import org.scalactic.source.Position
@@ -28,14 +29,16 @@ import org.slf4j.MDC
import play.api.Application
import play.api.inject.bind
import play.api.inject.guice.GuiceApplicationBuilder
+import scalaxb.CanWriteXML
import uk.gov.hmrc.excisemovementcontrolsystemapi.data.{MessageParams, XmlMessageGeneratorFactory}
+import uk.gov.hmrc.excisemovementcontrolsystemapi.factories.IEMessageFactory
import uk.gov.hmrc.excisemovementcontrolsystemapi.filters.MovementFilter
import uk.gov.hmrc.excisemovementcontrolsystemapi.models.MessageTypes
import uk.gov.hmrc.excisemovementcontrolsystemapi.models.MessageTypes.IE801
-import uk.gov.hmrc.excisemovementcontrolsystemapi.models.messages.IE801Message
+import uk.gov.hmrc.excisemovementcontrolsystemapi.models.messages.{IE801Message, IEMessage}
import uk.gov.hmrc.excisemovementcontrolsystemapi.repository.MovementRepository.MessageNotification
-import uk.gov.hmrc.excisemovementcontrolsystemapi.repository.model.{Message, Movement}
-import uk.gov.hmrc.excisemovementcontrolsystemapi.utils.DateTimeService
+import uk.gov.hmrc.excisemovementcontrolsystemapi.repository.model.{Message, MiscodedMovement, Movement}
+import uk.gov.hmrc.excisemovementcontrolsystemapi.utils.{DateTimeService, EmcsUtils}
import uk.gov.hmrc.mongo.MongoComponent
import uk.gov.hmrc.mongo.test.{CleanMongoCollectionSupport, DefaultPlayMongoRepositorySupport}
@@ -1028,6 +1031,138 @@ class MovementRepositoryItSpec
mustPreserveMdc(repository.addBoxIdToMessages("recipient1", "boxId3"))
}
+ "getMiscodedMessages" should {
+
+ val utils = new EmcsUtils
+ val messageFactory = IEMessageFactory()
+
+ def formatXmlIncorrectly[A, B <: IEMessage with ({ val obj: A })](ern: String, params: MessageParams)(implicit ev: CanWriteXML[A]): String = {
+ utils.encode(scalaxb.toXML(messageFactory.createFromXml(
+ params.messageType.value,
+ XmlMessageGeneratorFactory.generate(ern, params)
+ ).asInstanceOf[B].obj, s"${params.messageType.value}Type", generated.defaultScope).toString)
+ }
+
+ def formatXmlCorrectly[A, B <: IEMessage with ({ val obj: A })](ern: String, params: MessageParams)(implicit ev: CanWriteXML[A]): String = {
+ utils.encode(scalaxb.toXML(messageFactory.createFromXml(
+ params.messageType.value,
+ XmlMessageGeneratorFactory.generate(ern, params)
+ ).asInstanceOf[B].obj, params.messageType.value, generated.defaultScope).toString)
+ }
+
+ "return any movements where they have a message which is badly encoded" in {
+
+ val now = Instant.now().truncatedTo(ChronoUnit.MILLIS)
+
+ val lrn1 = "lrn1"
+ val arc1 = "arc1"
+ val lrn2 = "lrn2"
+ val arc2 = "arc2"
+
+ val consignor = "consignor"
+ val consignee = "consignee"
+
+ val badIe801 = formatXmlIncorrectly[IE801Type, IE801Message](consignor, MessageParams(IE801, "XI000001", consigneeErn = Some(consignee), localReferenceNumber = Some(lrn1), administrativeReferenceCode = Some(arc1)))
+ val goodIe801 = formatXmlCorrectly[IE801Type, IE801Message](consignor, MessageParams(IE801, "XI000002", consigneeErn = Some(consignee), localReferenceNumber = Some(lrn2), administrativeReferenceCode = Some(arc2)))
+
+ val movement1 = Movement(
+ boxId = None,
+ localReferenceNumber = lrn1,
+ consignorId = consignor,
+ consigneeId = Some(consignee),
+ administrativeReferenceCode = Some(arc1),
+ lastUpdated = now.minus(1, ChronoUnit.DAYS),
+ messages = Seq(
+ Message(badIe801, "IE801", "XI000001", consignor, Set.empty, now.minus(4, ChronoUnit.DAYS)),
+ )
+ )
+
+ val movement2 = Movement(
+ boxId = None,
+ localReferenceNumber = lrn2,
+ consignorId = consignor,
+ consigneeId = Some(consignee),
+ administrativeReferenceCode = Some(arc2),
+ lastUpdated = now.minus(1, ChronoUnit.DAYS),
+ messages = Seq(
+ Message(goodIe801, "IE801", "XI000002", consignor, Set.empty, now.minus(4, ChronoUnit.DAYS)),
+ )
+ )
+
+ insert(movement1).futureValue
+ insert(movement2).futureValue
+
+ val result = repository.getMiscodedMovements().futureValue
+
+ result must contain only MiscodedMovement(movement1._id)
+ }
+ }
+
+ "getCountOfMiscodedMessages" should {
+
+ val utils = new EmcsUtils
+ val messageFactory = IEMessageFactory()
+
+ def formatXmlIncorrectly[A, B <: IEMessage with ({ val obj: A })](ern: String, params: MessageParams)(implicit ev: CanWriteXML[A]): String = {
+ utils.encode(scalaxb.toXML(messageFactory.createFromXml(
+ params.messageType.value,
+ XmlMessageGeneratorFactory.generate(ern, params)
+ ).asInstanceOf[B].obj, s"${params.messageType.value}Type", generated.defaultScope).toString)
+ }
+
+ def formatXmlCorrectly[A, B <: IEMessage with ({ val obj: A })](ern: String, params: MessageParams)(implicit ev: CanWriteXML[A]): String = {
+ utils.encode(scalaxb.toXML(messageFactory.createFromXml(
+ params.messageType.value,
+ XmlMessageGeneratorFactory.generate(ern, params)
+ ).asInstanceOf[B].obj, params.messageType.value, generated.defaultScope).toString)
+ }
+
+ "return the count of how many movements have badly encoded messages" in {
+
+ val now = Instant.now().truncatedTo(ChronoUnit.MILLIS)
+
+ val lrn1 = "lrn1"
+ val arc1 = "arc1"
+ val lrn2 = "lrn2"
+ val arc2 = "arc2"
+
+ val consignor = "consignor"
+ val consignee = "consignee"
+
+ val badIe801 = formatXmlIncorrectly[IE801Type, IE801Message](consignor, MessageParams(IE801, "XI000001", consigneeErn = Some(consignee), localReferenceNumber = Some(lrn1), administrativeReferenceCode = Some(arc1)))
+ val goodIe801 = formatXmlCorrectly[IE801Type, IE801Message](consignor, MessageParams(IE801, "XI000002", consigneeErn = Some(consignee), localReferenceNumber = Some(lrn2), administrativeReferenceCode = Some(arc2)))
+
+ val movement1 = Movement(
+ boxId = None,
+ localReferenceNumber = lrn1,
+ consignorId = consignor,
+ consigneeId = Some(consignee),
+ administrativeReferenceCode = Some(arc1),
+ lastUpdated = now.minus(1, ChronoUnit.DAYS),
+ messages = Seq(
+ Message(badIe801, "IE801", "XI000001", consignor, Set.empty, now.minus(4, ChronoUnit.DAYS)),
+ )
+ )
+
+ val movement2 = Movement(
+ boxId = None,
+ localReferenceNumber = lrn2,
+ consignorId = consignor,
+ consigneeId = Some(consignee),
+ administrativeReferenceCode = Some(arc2),
+ lastUpdated = now.minus(1, ChronoUnit.DAYS),
+ messages = Seq(
+ Message(goodIe801, "IE801", "XI000002", consignor, Set.empty, now.minus(4, ChronoUnit.DAYS)),
+ )
+ )
+
+ insert(movement1).futureValue
+ insert(movement2).futureValue
+
+ repository.getCountOfMiscodedMovements().futureValue mustEqual 1
+ }
+ }
+
private def insertMovement(movement: Movement) =
insert(movement).futureValue
From 9d320f4c5f2a601f1b201f91c5ee0f79b59fe91f Mon Sep 17 00:00:00 2001
From: Michael Wolfendale <4563722+wolfendale@users.noreply.github.com>
Date: Thu, 26 Sep 2024 12:30:47 +0100
Subject: [PATCH 2/2] Add MiscodedMovementService
---
.../models/messages/IE905Message.scala | 2 +-
.../services/MiscodedMovementService.scala | 216 ++++++++++++++++++
.../MiscodedMovementServiceSpec.scala | 212 +++++++++++++++++
.../data/XmlMessageGenerator.scala | 32 +++
4 files changed, 461 insertions(+), 1 deletion(-)
create mode 100644 app/uk/gov/hmrc/excisemovementcontrolsystemapi/services/MiscodedMovementService.scala
create mode 100644 it/test/uk/gov/hmrc/excisemovementcontrolsystemapi/services/MiscodedMovementServiceSpec.scala
diff --git a/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE905Message.scala b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE905Message.scala
index 20892dde..e15d646e 100644
--- a/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE905Message.scala
+++ b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/models/messages/IE905Message.scala
@@ -27,7 +27,7 @@ import uk.gov.hmrc.excisemovementcontrolsystemapi.models.messages.MessageTypeFor
import scala.xml.NodeSeq
case class IE905Message(
- private val obj: IE905Type,
+ obj: IE905Type,
key: Option[String],
namespace: Option[String],
auditType: AuditType
diff --git a/app/uk/gov/hmrc/excisemovementcontrolsystemapi/services/MiscodedMovementService.scala b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/services/MiscodedMovementService.scala
new file mode 100644
index 00000000..c6ef9a9a
--- /dev/null
+++ b/app/uk/gov/hmrc/excisemovementcontrolsystemapi/services/MiscodedMovementService.scala
@@ -0,0 +1,216 @@
+/*
+ * Copyright 2024 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.excisemovementcontrolsystemapi.services
+
+import org.apache.pekko.Done
+import play.api.Logging
+import uk.gov.hmrc.excisemovementcontrolsystemapi.factories.IEMessageFactory
+import uk.gov.hmrc.excisemovementcontrolsystemapi.models.MessageTypes._
+import uk.gov.hmrc.excisemovementcontrolsystemapi.models.messages._
+import uk.gov.hmrc.excisemovementcontrolsystemapi.repository.MovementRepository
+import uk.gov.hmrc.excisemovementcontrolsystemapi.repository.model.Message
+import uk.gov.hmrc.excisemovementcontrolsystemapi.utils.EmcsUtils
+
+import javax.inject.{Inject, Singleton}
+import scala.concurrent.{ExecutionContext, Future}
+import scala.xml.XML
+
+@Singleton
+class MiscodedMovementService @Inject() (
+ movementRepository: MovementRepository,
+ emcsUtils: EmcsUtils,
+ messageFactory: IEMessageFactory
+)(implicit ec: ExecutionContext)
+ extends Logging {
+
+ def recodeMessages(movementId: String): Future[Done] =
+ movementRepository.getMovementById(movementId).flatMap {
+ _.map { movement =>
+ val updatedMessages = movement.messages.map(recodeMessage)
+ movementRepository.save(movement.copy(messages = updatedMessages))
+ }.getOrElse {
+ logger.warn(s"No movement found for id: $movementId")
+ Future.successful(Done)
+ }
+ }
+
+ private def recodeMessage(message: Message): Message = {
+
+ val xml = XML.loadString(emcsUtils.decode(message.encodedMessage))
+
+ val updatedMessage = xml.headOption.flatMap { node =>
+ if (node.label.endsWith("Type")) {
+ messageFactory.createFromXml(message.messageType, xml) match {
+ case ie704: IE704Message =>
+ Some(
+ scalaxb.toXML(
+ ie704.obj,
+ Some("http://www.govtalk.gov.uk/taxation/InternationalTrade/Excise/ie704uk/3"),
+ Some(IE704.value),
+ generated.defaultScope
+ )
+ )
+ case ie801: IE801Message =>
+ Some(
+ scalaxb.toXML(
+ ie801.obj,
+ Some("urn:publicid:-:EC:DGTAXUD:EMCS:PHASE4:IE801:V3.13"),
+ Some(IE801.value),
+ generated.defaultScope
+ )
+ )
+ case ie802: IE802Message =>
+ Some(
+ scalaxb.toXML(
+ ie802.obj,
+ Some("urn:publicid:-:EC:DGTAXUD:EMCS:PHASE4:IE802:V3.13"),
+ Some(IE802.value),
+ generated.defaultScope
+ )
+ )
+ case ie803: IE803Message =>
+ Some(
+ scalaxb.toXML(
+ ie803.obj,
+ Some("urn:publicid:-:EC:DGTAXUD:EMCS:PHASE4:IE803:V3.13"),
+ Some(IE803.value),
+ generated.defaultScope
+ )
+ )
+ case ie807: IE807Message =>
+ Some(
+ scalaxb.toXML(
+ ie807.obj,
+ Some("urn:publicid:-:EC:DGTAXUD:EMCS:PHASE4:IE807:V3.13"),
+ Some(IE807.value),
+ generated.defaultScope
+ )
+ )
+ case ie810: IE810Message =>
+ Some(
+ scalaxb.toXML(
+ ie810.obj,
+ Some("urn:publicid:-:EC:DGTAXUD:EMCS:PHASE4:IE810:V3.13"),
+ Some(IE810.value),
+ generated.defaultScope
+ )
+ )
+ case ie813: IE813Message =>
+ Some(
+ scalaxb.toXML(
+ ie813.obj,
+ Some("urn:publicid:-:EC:DGTAXUD:EMCS:PHASE4:IE813:V3.13"),
+ Some(IE813.value),
+ generated.defaultScope
+ )
+ )
+ case ie818: IE818Message =>
+ Some(
+ scalaxb.toXML(
+ ie818.obj,
+ Some("urn:publicid:-:EC:DGTAXUD:EMCS:PHASE4:IE818:V3.13"),
+ Some(IE818.value),
+ generated.defaultScope
+ )
+ )
+ case ie819: IE819Message =>
+ Some(
+ scalaxb.toXML(
+ ie819.obj,
+ Some("urn:publicid:-:EC:DGTAXUD:EMCS:PHASE4:IE819:V3.13"),
+ Some(IE819.value),
+ generated.defaultScope
+ )
+ )
+ case ie829: IE829Message =>
+ Some(
+ scalaxb.toXML(
+ ie829.obj,
+ Some("urn:publicid:-:EC:DGTAXUD:EMCS:PHASE4:IE829:V3.13"),
+ Some(IE829.value),
+ generated.defaultScope
+ )
+ )
+ case ie837: IE837Message =>
+ Some(
+ scalaxb.toXML(
+ ie837.obj,
+ Some("urn:publicid:-:EC:DGTAXUD:EMCS:PHASE4:IE837:V3.13"),
+ Some(IE837.value),
+ generated.defaultScope
+ )
+ )
+ case ie839: IE839Message =>
+ Some(
+ scalaxb.toXML(
+ ie839.obj,
+ Some("urn:publicid:-:EC:DGTAXUD:EMCS:PHASE4:IE839:V3.13"),
+ Some(IE839.value),
+ generated.defaultScope
+ )
+ )
+ case ie840: IE840Message =>
+ Some(
+ scalaxb.toXML(
+ ie840.obj,
+ Some("urn:publicid:-:EC:DGTAXUD:EMCS:PHASE4:IE840:V3.13"),
+ Some(IE840.value),
+ generated.defaultScope
+ )
+ )
+ case ie871: IE871Message =>
+ Some(
+ scalaxb.toXML(
+ ie871.obj,
+ Some("urn:publicid:-:EC:DGTAXUD:EMCS:PHASE4:IE871:V3.13"),
+ Some(IE871.value),
+ generated.defaultScope
+ )
+ )
+ case ie881: IE881Message =>
+ Some(
+ scalaxb.toXML(
+ ie881.obj,
+ Some("urn:publicid:-:EC:DGTAXUD:EMCS:PHASE4:IE881:V3.13"),
+ Some(IE881.value),
+ generated.defaultScope
+ )
+ )
+ case ie905: IE905Message =>
+ Some(
+ scalaxb.toXML(
+ ie905.obj,
+ Some("urn:publicid:-:EC:DGTAXUD:EMCS:PHASE4:IE905:V3.13"),
+ Some(IE905.value),
+ generated.defaultScope
+ )
+ )
+ case _ => None
+ }
+ } else {
+ None
+ }
+ }
+
+ updatedMessage
+ .map { updatedMessage =>
+ val recodedMessage = emcsUtils.encode(updatedMessage.toString)
+ message.copy(encodedMessage = recodedMessage, hash = recodedMessage.hashCode)
+ }
+ .getOrElse(message)
+ }
+}
diff --git a/it/test/uk/gov/hmrc/excisemovementcontrolsystemapi/services/MiscodedMovementServiceSpec.scala b/it/test/uk/gov/hmrc/excisemovementcontrolsystemapi/services/MiscodedMovementServiceSpec.scala
new file mode 100644
index 00000000..119842ed
--- /dev/null
+++ b/it/test/uk/gov/hmrc/excisemovementcontrolsystemapi/services/MiscodedMovementServiceSpec.scala
@@ -0,0 +1,212 @@
+/*
+ * Copyright 2024 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.excisemovementcontrolsystemapi.services
+
+import generated.{IE704Type, IE801Type, IE802Type, IE803Type, IE807Type, IE810Type, IE813Type, IE818Type, IE819Type, IE829Type, IE837Type, IE839Type, IE840Type, IE871Type, IE881Type, IE905Type}
+import org.mockito.MockitoSugar
+import org.scalatest.concurrent.IntegrationPatience
+import org.scalatest.{BeforeAndAfterAll, BeforeAndAfterEach, EitherValues}
+import org.scalatestplus.play.PlaySpec
+import org.scalatestplus.play.guice.GuiceOneAppPerSuite
+import play.api.Application
+import play.api.inject.bind
+import play.api.inject.guice.GuiceApplicationBuilder
+import scalaxb.CanWriteXML
+import uk.gov.hmrc.excisemovementcontrolsystemapi.data.{MessageParams, XmlMessageGeneratorFactory}
+import uk.gov.hmrc.excisemovementcontrolsystemapi.factories.IEMessageFactory
+import uk.gov.hmrc.excisemovementcontrolsystemapi.models.MessageTypes.{IE704, IE801, IE802, IE803, IE807, IE810, IE813, IE818, IE819, IE829, IE837, IE839, IE840, IE871, IE881, IE905}
+import uk.gov.hmrc.excisemovementcontrolsystemapi.models.messages._
+import uk.gov.hmrc.excisemovementcontrolsystemapi.repository.MovementRepository
+import uk.gov.hmrc.excisemovementcontrolsystemapi.repository.model.{Message, Movement}
+import uk.gov.hmrc.excisemovementcontrolsystemapi.utils.{DateTimeService, EmcsUtils}
+import uk.gov.hmrc.mongo.MongoComponent
+import uk.gov.hmrc.mongo.test.CleanMongoCollectionSupport
+
+import java.time.Instant
+import java.time.temporal.ChronoUnit
+
+class MiscodedMovementServiceSpec
+ extends PlaySpec
+ with CleanMongoCollectionSupport
+ with EitherValues
+ with IntegrationPatience
+ with BeforeAndAfterEach
+ with BeforeAndAfterAll
+ with GuiceOneAppPerSuite
+ with MockitoSugar {
+
+ private val dateTimeService = mock[DateTimeService]
+ private val now = Instant.now.truncatedTo(ChronoUnit.MILLIS)
+
+ override def fakeApplication(): Application = GuiceApplicationBuilder()
+ .overrides(
+ bind[MongoComponent].toInstance(mongoComponent),
+ bind[DateTimeService].toInstance(dateTimeService)
+ )
+ .build()
+
+ private lazy val movementRepository: MovementRepository = app.injector.instanceOf[MovementRepository]
+ private lazy val miscodedMovementService = app.injector.instanceOf[MiscodedMovementService]
+
+ private val utils = new EmcsUtils
+ private val messageFactory = IEMessageFactory()
+
+ override def beforeEach(): Unit = {
+ super.beforeEach()
+ when(dateTimeService.timestamp()).thenReturn(now)
+ }
+
+ "recodeMessages" should {
+
+ "recode the messages for the given movement" in {
+
+ val lrn = "lrn"
+ val arc = "arc"
+
+ val consignor = "consignor"
+ val consignee = "consignee"
+
+ val badIe704 = formatXmlIncorrectly[IE704Type, IE704Message](consignor, MessageParams(IE704, "XI000000", consigneeErn = Some(consignee), localReferenceNumber = Some(lrn), administrativeReferenceCode = None))
+ val goodIe704 = formatXmlCorrectly[IE704Type, IE704Message](consignor, MessageParams(IE704, "XI000000", consigneeErn = Some(consignee), localReferenceNumber = Some(lrn), administrativeReferenceCode = None), "http://www.govtalk.gov.uk/taxation/InternationalTrade/Excise/ie704uk/3")
+
+ val badIe801 = formatXmlIncorrectly[IE801Type, IE801Message](consignor, MessageParams(IE801, "XI000001", consigneeErn = Some(consignee), localReferenceNumber = Some(lrn), administrativeReferenceCode = Some(arc)))
+ val goodIe801 = formatXmlCorrectly[IE801Type, IE801Message](consignor, MessageParams(IE801, "XI000001", consigneeErn = Some(consignee), localReferenceNumber = Some(lrn), administrativeReferenceCode = Some(arc)), "urn:publicid:-:EC:DGTAXUD:EMCS:PHASE4:IE801:V3.13")
+
+ val badIe802 = formatXmlIncorrectly[IE802Type, IE802Message](consignor, MessageParams(IE802, "XI000002", consigneeErn = None, localReferenceNumber = None, administrativeReferenceCode = Some(arc)))
+ val goodIe802 = formatXmlCorrectly[IE802Type, IE802Message](consignor, MessageParams(IE802, "XI000002", consigneeErn = None, localReferenceNumber = None, administrativeReferenceCode = Some(arc)), "urn:publicid:-:EC:DGTAXUD:EMCS:PHASE4:IE802:V3.13")
+
+ val badIe803 = formatXmlIncorrectly[IE803Type, IE803Message](consignor, MessageParams(IE803, "XI000003", consigneeErn = None, localReferenceNumber = None, administrativeReferenceCode = Some(arc)))
+ val goodIe803 = formatXmlCorrectly[IE803Type, IE803Message](consignor, MessageParams(IE803, "XI000003", consigneeErn = None, localReferenceNumber = None, administrativeReferenceCode = Some(arc)), "urn:publicid:-:EC:DGTAXUD:EMCS:PHASE4:IE803:V3.13")
+
+ val badIe807 = formatXmlIncorrectly[IE807Type, IE807Message](consignor, MessageParams(IE807, "XI000004", consigneeErn = None, localReferenceNumber = None, administrativeReferenceCode = Some(arc)))
+ val goodIe807 = formatXmlCorrectly[IE807Type, IE807Message](consignor, MessageParams(IE807, "XI000004", consigneeErn = None, localReferenceNumber = None, administrativeReferenceCode = Some(arc)), "urn:publicid:-:EC:DGTAXUD:EMCS:PHASE4:IE807:V3.13")
+
+ val badIe810 = formatXmlIncorrectly[IE810Type, IE810Message](consignor, MessageParams(IE810, "XI000005", consigneeErn = None, localReferenceNumber = None, administrativeReferenceCode = Some(arc)))
+ val goodIe810 = formatXmlCorrectly[IE810Type, IE810Message](consignor, MessageParams(IE810, "XI000005", consigneeErn = None, localReferenceNumber = None, administrativeReferenceCode = Some(arc)), "urn:publicid:-:EC:DGTAXUD:EMCS:PHASE4:IE810:V3.13")
+
+ val badIe813 = formatXmlIncorrectly[IE813Type, IE813Message](consignor, MessageParams(IE813, "XI000006", consigneeErn = Some(consignee), localReferenceNumber = None, administrativeReferenceCode = Some(arc)))
+ val goodIe813 = formatXmlCorrectly[IE813Type, IE813Message](consignor, MessageParams(IE813, "XI000006", consigneeErn = Some(consignee), localReferenceNumber = None, administrativeReferenceCode = Some(arc)), "urn:publicid:-:EC:DGTAXUD:EMCS:PHASE4:IE813:V3.13")
+
+ val badIe818 = formatXmlIncorrectly[IE818Type, IE818Message](consignor, MessageParams(IE818, "XI000008", consigneeErn = Some(consignee), localReferenceNumber = None, administrativeReferenceCode = Some(arc)))
+ val goodIe818 = formatXmlCorrectly[IE818Type, IE818Message](consignor, MessageParams(IE818, "XI000008", consigneeErn = Some(consignee), localReferenceNumber = None, administrativeReferenceCode = Some(arc)), "urn:publicid:-:EC:DGTAXUD:EMCS:PHASE4:IE818:V3.13")
+
+ val badIe819 = formatXmlIncorrectly[IE819Type, IE819Message](consignor, MessageParams(IE819, "XI000009", consigneeErn = Some(consignee), localReferenceNumber = None, administrativeReferenceCode = Some(arc)))
+ val goodIe819 = formatXmlCorrectly[IE819Type, IE819Message](consignor, MessageParams(IE819, "XI000009", consigneeErn = Some(consignee), localReferenceNumber = None, administrativeReferenceCode = Some(arc)), "urn:publicid:-:EC:DGTAXUD:EMCS:PHASE4:IE819:V3.13")
+
+ val badIe829 = formatXmlIncorrectly[IE829Type, IE829Message](consignor, MessageParams(IE829, "XI000010", consigneeErn = Some(consignee), localReferenceNumber = None, administrativeReferenceCode = Some(arc)))
+ val goodIe829 = formatXmlCorrectly[IE829Type, IE829Message](consignor, MessageParams(IE829, "XI000010", consigneeErn = Some(consignee), localReferenceNumber = None, administrativeReferenceCode = Some(arc)), "urn:publicid:-:EC:DGTAXUD:EMCS:PHASE4:IE829:V3.13")
+
+ val badIe837 = formatXmlIncorrectly[IE837Type, IE837Message](consignor, MessageParams(IE837, "XI000011", consigneeErn = None, localReferenceNumber = None, administrativeReferenceCode = Some(arc)))
+ val goodIe837 = formatXmlCorrectly[IE837Type, IE837Message](consignor, MessageParams(IE837, "XI000011", consigneeErn = None, localReferenceNumber = None, administrativeReferenceCode = Some(arc)), "urn:publicid:-:EC:DGTAXUD:EMCS:PHASE4:IE837:V3.13")
+
+ val badIe839 = formatXmlIncorrectly[IE839Type, IE839Message](consignor, MessageParams(IE839, "XI000012", consigneeErn = Some(consignee), localReferenceNumber = Some(lrn), administrativeReferenceCode = Some(arc)))
+ val goodIe839 = formatXmlCorrectly[IE839Type, IE839Message](consignor, MessageParams(IE839, "XI000012", consigneeErn = Some(consignee), localReferenceNumber = Some(lrn), administrativeReferenceCode = Some(arc)), "urn:publicid:-:EC:DGTAXUD:EMCS:PHASE4:IE839:V3.13")
+
+ val badIe840 = formatXmlIncorrectly[IE840Type, IE840Message](consignor, MessageParams(IE840, "XI000013", consigneeErn = None, localReferenceNumber = None, administrativeReferenceCode = Some(arc)))
+ val goodIe840 = formatXmlCorrectly[IE840Type, IE840Message](consignor, MessageParams(IE840, "XI000013", consigneeErn = None, localReferenceNumber = None, administrativeReferenceCode = Some(arc)), "urn:publicid:-:EC:DGTAXUD:EMCS:PHASE4:IE840:V3.13")
+
+ val badIe871 = formatXmlIncorrectly[IE871Type, IE871Message](consignor, MessageParams(IE871, "XI000014", consigneeErn = Some(consignee), localReferenceNumber = None, administrativeReferenceCode = Some(arc)))
+ val goodIe871 = formatXmlCorrectly[IE871Type, IE871Message](consignor, MessageParams(IE871, "XI000014", consigneeErn = Some(consignee), localReferenceNumber = None, administrativeReferenceCode = Some(arc)), "urn:publicid:-:EC:DGTAXUD:EMCS:PHASE4:IE871:V3.13")
+
+ val badIe881 = formatXmlIncorrectly[IE881Type, IE881Message](consignor, MessageParams(IE881, "XI000015", consigneeErn = None, localReferenceNumber = None, administrativeReferenceCode = Some(arc)))
+ val goodIe881 = formatXmlCorrectly[IE881Type, IE881Message](consignor, MessageParams(IE881, "XI000015", consigneeErn = None, localReferenceNumber = None, administrativeReferenceCode = Some(arc)), "urn:publicid:-:EC:DGTAXUD:EMCS:PHASE4:IE881:V3.13")
+
+ val badIe905 = formatXmlIncorrectly[IE905Type, IE905Message](consignor, MessageParams(IE905, "XI000016", consigneeErn = None, localReferenceNumber = None, administrativeReferenceCode = Some(arc)))
+ val goodIe905 = formatXmlCorrectly[IE905Type, IE905Message](consignor, MessageParams(IE905, "XI000016", consigneeErn = None, localReferenceNumber = None, administrativeReferenceCode = Some(arc)), "urn:publicid:-:EC:DGTAXUD:EMCS:PHASE4:IE905:V3.13")
+
+ // Here we're renaming the default namespace for the IE704 to show that if the message element doesn't end in `Type` then we won't replace it
+ val ignoredMessage = {
+ utils.encode(
+ utils.decode(
+ formatXmlCorrectly[IE704Type, IE704Message](consignor, MessageParams(IE704, "XI000017", consigneeErn = Some(consignee), localReferenceNumber = Some(lrn), administrativeReferenceCode = None), "http://www.govtalk.gov.uk/taxation/InternationalTrade/Excise/ie704uk/3")
+ ).replaceAll("ie704uk:", "foo:").replace("xmlns:ie704uk=", "xmlns:foo=")
+ )
+ }
+
+ val movement = Movement(
+ boxId = None,
+ localReferenceNumber = lrn,
+ consignorId = consignor,
+ consigneeId = Some(consignee),
+ administrativeReferenceCode = Some(arc),
+ lastUpdated = now.minus(1, ChronoUnit.DAYS),
+ messages = Seq(
+ Message(badIe704, "IE704", "XI000000", consignee, Set.empty, now.minus(4, ChronoUnit.DAYS)),
+ Message(badIe801, "IE801", "XI000001", consignee, Set.empty, now.minus(4, ChronoUnit.DAYS)),
+ Message(badIe802, "IE802", "XI000002", consignee, Set.empty, now.minus(4, ChronoUnit.DAYS)),
+ Message(badIe803, "IE803", "XI000003", consignee, Set.empty, now.minus(4, ChronoUnit.DAYS)),
+ Message(badIe807, "IE807", "XI000004", consignee, Set.empty, now.minus(4, ChronoUnit.DAYS)),
+ Message(badIe810, "IE810", "XI000005", consignee, Set.empty, now.minus(4, ChronoUnit.DAYS)),
+ Message(badIe813, "IE813", "XI000006", consignee, Set.empty, now.minus(4, ChronoUnit.DAYS)),
+ Message(badIe818, "IE818", "XI000008", consignee, Set.empty, now.minus(4, ChronoUnit.DAYS)),
+ Message(badIe819, "IE819", "XI000009", consignee, Set.empty, now.minus(4, ChronoUnit.DAYS)),
+ Message(badIe829, "IE829", "XI000010", consignee, Set.empty, now.minus(4, ChronoUnit.DAYS)),
+ Message(badIe837, "IE837", "XI000011", consignee, Set.empty, now.minus(4, ChronoUnit.DAYS)),
+ Message(badIe839, "IE839", "XI000012", consignee, Set.empty, now.minus(4, ChronoUnit.DAYS)),
+ Message(badIe840, "IE840", "XI000013", consignee, Set.empty, now.minus(4, ChronoUnit.DAYS)),
+ Message(badIe871, "IE871", "XI000014", consignee, Set.empty, now.minus(4, ChronoUnit.DAYS)),
+ Message(badIe881, "IE881", "XI000015", consignee, Set.empty, now.minus(4, ChronoUnit.DAYS)),
+ Message(badIe905, "IE905", "XI000016", consignee, Set.empty, now.minus(4, ChronoUnit.DAYS)),
+ Message(ignoredMessage, "IE704", "XI000017", consignee, Set.empty, now.minus(4, ChronoUnit.DAYS))
+ )
+ )
+
+ val expectedMovement = movement.copy(
+ messages = Seq(
+ Message(goodIe704, "IE704", "XI000000", consignee, Set.empty, now.minus(4, ChronoUnit.DAYS)),
+ Message(goodIe801, "IE801", "XI000001", consignee, Set.empty, now.minus(4, ChronoUnit.DAYS)),
+ Message(goodIe802, "IE802", "XI000002", consignee, Set.empty, now.minus(4, ChronoUnit.DAYS)),
+ Message(goodIe803, "IE803", "XI000003", consignee, Set.empty, now.minus(4, ChronoUnit.DAYS)),
+ Message(goodIe807, "IE807", "XI000004", consignee, Set.empty, now.minus(4, ChronoUnit.DAYS)),
+ Message(goodIe810, "IE810", "XI000005", consignee, Set.empty, now.minus(4, ChronoUnit.DAYS)),
+ Message(goodIe813, "IE813", "XI000006", consignee, Set.empty, now.minus(4, ChronoUnit.DAYS)),
+ Message(goodIe818, "IE818", "XI000008", consignee, Set.empty, now.minus(4, ChronoUnit.DAYS)),
+ Message(goodIe819, "IE819", "XI000009", consignee, Set.empty, now.minus(4, ChronoUnit.DAYS)),
+ Message(goodIe829, "IE829", "XI000010", consignee, Set.empty, now.minus(4, ChronoUnit.DAYS)),
+ Message(goodIe837, "IE837", "XI000011", consignee, Set.empty, now.minus(4, ChronoUnit.DAYS)),
+ Message(goodIe839, "IE839", "XI000012", consignee, Set.empty, now.minus(4, ChronoUnit.DAYS)),
+ Message(goodIe840, "IE840", "XI000013", consignee, Set.empty, now.minus(4, ChronoUnit.DAYS)),
+ Message(goodIe871, "IE871", "XI000014", consignee, Set.empty, now.minus(4, ChronoUnit.DAYS)),
+ Message(goodIe881, "IE881", "XI000015", consignee, Set.empty, now.minus(4, ChronoUnit.DAYS)),
+ Message(goodIe905, "IE905", "XI000016", consignee, Set.empty, now.minus(4, ChronoUnit.DAYS)),
+ Message(ignoredMessage, "IE704", "XI000017", consignee, Set.empty, now.minus(4, ChronoUnit.DAYS))
+ )
+ )
+
+ movementRepository.save(movement).futureValue
+ miscodedMovementService.recodeMessages(movement._id).futureValue
+
+ val result = movementRepository.getMovementById(movement._id).futureValue.value
+
+ result mustEqual expectedMovement
+ }
+ }
+
+ private def formatXmlIncorrectly[A, B <: IEMessage with ({ val obj: A })](ern: String, params: MessageParams)(implicit ev: CanWriteXML[A]): String = {
+ utils.encode(scalaxb.toXML(messageFactory.createFromXml(
+ params.messageType.value,
+ XmlMessageGeneratorFactory.generate(ern, params)
+ ).asInstanceOf[B].obj, s"${params.messageType.value}Type", generated.defaultScope).toString)
+ }
+
+ private def formatXmlCorrectly[A, B <: IEMessage with ({ val obj: A })](ern: String, params: MessageParams, namespace: String)(implicit ev: CanWriteXML[A]): String = {
+ utils.encode(scalaxb.toXML(messageFactory.createFromXml(
+ params.messageType.value,
+ XmlMessageGeneratorFactory.generate(ern, params)
+ ).asInstanceOf[B].obj, Some(namespace), Some(params.messageType.value), generated.defaultScope).toString)
+ }
+}
diff --git a/test/uk/gov/hmrc/excisemovementcontrolsystemapi/data/XmlMessageGenerator.scala b/test/uk/gov/hmrc/excisemovementcontrolsystemapi/data/XmlMessageGenerator.scala
index 9fc2ea86..06449446 100644
--- a/test/uk/gov/hmrc/excisemovementcontrolsystemapi/data/XmlMessageGenerator.scala
+++ b/test/uk/gov/hmrc/excisemovementcontrolsystemapi/data/XmlMessageGenerator.scala
@@ -39,6 +39,7 @@ object XmlMessageGeneratorFactory extends XmlMessageGenerator {
case IE818 => IE818XmlMessageGenerator.generate(ern, params)
case IE819 => IE819XmlMessageGenerator.generate(ern, params)
case IE829 => IE829XmlMessageGenerator.generate(ern, params)
+ case IE837 => IE837XmlMessageGenerator.generate(ern, params)
case IE839 => IE839XmlMessageGenerator.generate(ern, params)
case IE840 => IE840XmlMessageGenerator.generate(ern, params)
case IE871 => IE871XmlMessageGenerator.generate(ern, params)
@@ -566,6 +567,37 @@ private case object IE829XmlMessageGenerator extends XmlMessageGenerator {
}
+private case object IE837XmlMessageGenerator extends XmlMessageGenerator {
+ override def generate(ern: String, params: MessageParams): NodeSeq =
+
+
+ NDEA.GB
+ NDEA.EU
+ 2023-08-10
+ 09:56:40.695540
+ {params.messageIdentifier}
+ a2f65a81-c297-4117-bea5-556129529463
+
+
+
+
+ {ern}
+ 2
+ 6
+ Accident on M5
+ 1
+ 2023-08-10T10:56:42
+
+
+ {params.administrativeReferenceCode}
+ 2
+
+
+
+
+}
+
private case object IE839XmlMessageGenerator extends XmlMessageGenerator {
override def generate(ern: String, params: MessageParams): NodeSeq =