Skip to content

Commit

Permalink
Merge pull request #233 from hmrc/EMCS-731
Browse files Browse the repository at this point in the history
EMCS-731 Movement Details Admin Endpoint
  • Loading branch information
RobertLaverick authored Oct 21, 2024
2 parents 1d1e697 + 5c20a60 commit 7ae5d8b
Show file tree
Hide file tree
Showing 3 changed files with 215 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* 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.controllers

import play.api.libs.json.{Json, OFormat}
import play.api.mvc.{Action, AnyContent, ControllerComponents}
import uk.gov.hmrc.excisemovementcontrolsystemapi.repository.MovementRepository
import uk.gov.hmrc.excisemovementcontrolsystemapi.repository.model.Movement
import uk.gov.hmrc.internalauth.client.{BackendAuthComponents, IAAction, Predicate, Resource, ResourceLocation, ResourceType, Retrieval}
import uk.gov.hmrc.play.bootstrap.backend.controller.BackendController

import java.time.Instant
import javax.inject.{Inject, Singleton}
import scala.concurrent.ExecutionContext

@Singleton
class AdminDetailsController @Inject() (
cc: ControllerComponents,
auth: BackendAuthComponents,
movementRepository: MovementRepository
)(implicit
ec: ExecutionContext
) extends BackendController(cc) {
private val permission = Predicate.Permission(
Resource(ResourceType("excise-movement-control-system-api"), ResourceLocation("admin/movement")),
IAAction("ADMIN")
)

private val authorised = auth.authorizedAction(
predicate = permission,
retrieval = Retrieval.EmptyRetrieval
)

def getMovementDetails(movementId: String): Action[AnyContent] = authorised.async { implicit request =>
movementRepository.getMovementById(movementId).map { m =>
m match {
case Some(movement) => Ok(Json.toJson(MovementDetails.createFromMovement(movement)))
case None => NotFound(s"No Movement Found with id: $movementId")
}
}
}
}

case class MovementDetails(
id: String,
boxId: Option[String],
lrn: String,
consignorId: String,
consigneeId: Option[String],
arc: Option[String],
lastUpdated: Instant,
messageDetails: Seq[MessageDetails]
)

object MovementDetails {
def createFromMovement(m: Movement): MovementDetails =
MovementDetails(
m._id,
m.boxId,
m.localReferenceNumber,
m.consignorId,
m.consigneeId,
m.administrativeReferenceCode,
m.lastUpdated,
MessageDetails.createFromMovement(m)
)

implicit lazy val format: OFormat[MovementDetails] = Json.format
}
case class MessageDetails(id: String, messageType: String, recipient: String, boxes: Set[String], createdOn: Instant)

object MessageDetails {
def createFromMovement(movement: Movement): Seq[MessageDetails] =
movement.messages.map { m =>
MessageDetails(m.messageId, m.messageType, m.recipient, m.boxesToNotify, m.createdOn)
}
implicit lazy val format: OFormat[MessageDetails] = Json.format

}
3 changes: 3 additions & 0 deletions conf/app.routes
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,7 @@ GET /admin/miscoded-movements uk.gov.hmrc.excisemoveme
GET /admin/miscoded-movements/build-work-list uk.gov.hmrc.excisemovementcontrolsystemapi.controllers.MiscodedMovementController.buildWorkList()
POST /admin/miscoded-movements/resolve uk.gov.hmrc.excisemovementcontrolsystemapi.controllers.MiscodedMovementController.resolve()

GET /admin/movements/:movementId/details uk.gov.hmrc.excisemovementcontrolsystemapi.controllers.AdminDetailsController.getMovementDetails(movementId: String)

GET /admin/:ern/summary uk.gov.hmrc.excisemovementcontrolsystemapi.controllers.RemoveErnsAdminController.findAllReferencesToErn(ern: String)

Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/*
* 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.controllers

import org.mockito.ArgumentMatchers.any
import org.mockito.MockitoSugar.{reset, when}
import org.scalatest.BeforeAndAfterEach
import org.scalatestplus.mockito.MockitoSugar.mock
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 play.api.libs.json.Json
import play.api.mvc.Result
import play.api.test.Helpers._
import play.api.test.{FakeRequest, Helpers}
import uk.gov.hmrc.excisemovementcontrolsystemapi.repository.model.{Message, Movement}
import uk.gov.hmrc.excisemovementcontrolsystemapi.repository.{BoxIdRepository, ErnRetrievalRepository, ErnSubmissionRepository, MovementRepository}
import uk.gov.hmrc.internalauth.client._
import uk.gov.hmrc.internalauth.client.test.{BackendAuthComponentsStub, StubBehaviour}

import java.time.Instant
import scala.concurrent.{ExecutionContext, Future}

class AdminDetailsControllerSpec extends PlaySpec with GuiceOneAppPerSuite with BeforeAndAfterEach {

private val mockStubBehaviour = mock[StubBehaviour]
private val mockMovementRepository = mock[MovementRepository]

val backendAuthComponentsStub: BackendAuthComponents =
BackendAuthComponentsStub(mockStubBehaviour)(Helpers.stubControllerComponents(), ExecutionContext.global)

override def fakeApplication(): Application =
new GuiceApplicationBuilder()
.overrides(
bind[BackendAuthComponents].toInstance(backendAuthComponentsStub),
bind[MovementRepository].toInstance(mockMovementRepository)
)
.build()

override def beforeEach(): Unit = {
super.beforeEach()
reset(mockMovementRepository, mockStubBehaviour)
}

private val expectedPredicate = Predicate.Permission(
Resource(ResourceType("excise-movement-control-system-api"), ResourceLocation("admin/movement")),
IAAction("ADMIN")
)

"getMovementDetails" must {
"return OK with a json payload of movement details as expected for an existing id" in {
val testErn = "apples"
val timestamp = Instant.now()

val movement = Movement(
"testId",
None,
"lrn",
testErn,
Some(testErn),
None,
timestamp,
Seq(Message("messageCode", "IE801", "message_id", testErn, Set.empty, timestamp))
)

when(mockStubBehaviour.stubAuth(Some(expectedPredicate), Retrieval.EmptyRetrieval))
.thenReturn(Future.successful(()))

when(mockMovementRepository.getMovementById(any))
.thenReturn(Future.successful(Some(movement)))

val expectedResult = MovementDetails.createFromMovement(movement)

val fakeRequest =
FakeRequest(routes.AdminDetailsController.getMovementDetails("testId"))
.withHeaders("Authorization" -> "Token some-token")

val result: Future[Result] = route(app, fakeRequest).value

contentAsJson(result) mustBe Json.toJson(expectedResult)
status(result) mustBe OK
}

"return NotFound for the movementId" in {

when(mockStubBehaviour.stubAuth(Some(expectedPredicate), Retrieval.EmptyRetrieval))
.thenReturn(Future.successful(()))

when(mockMovementRepository.getMovementById(any))
.thenReturn(Future.successful(None))

val fakeRequest =
FakeRequest(routes.AdminDetailsController.getMovementDetails("testId"))
.withHeaders("Authorization" -> "Token some-token")

val result: Future[Result] = route(app, fakeRequest).value

contentAsString(result) mustBe s"No Movement Found with id: testId"
status(result) mustBe NOT_FOUND
}
}

}

0 comments on commit 7ae5d8b

Please sign in to comment.