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 =