Skip to content

Commit

Permalink
Merge pull request #41 from hmrc/RAS-460
Browse files Browse the repository at this point in the history
Ras 460
  • Loading branch information
RaminEsfandiari authored Oct 3, 2017
2 parents 8fcf631 + c4e0893 commit 0883ace
Show file tree
Hide file tree
Showing 9 changed files with 246 additions and 41 deletions.
1 change: 1 addition & 0 deletions app/uk/gov/hmrc/rasapi/config/AppContext.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,5 @@ object AppContext extends ServicesConfig {
lazy val residencyStatusUrl = current.configuration.getString("endpoints.residency-status.url").getOrElse(throw new RuntimeException(s"Missing Key $env.endpoints.residency-status.url"))
lazy val desAuthToken = current.configuration.getString("desauthtoken").getOrElse(throw new RuntimeException(s"Missing Key $env.desauthtoken"))
lazy val desUrlHeaderEnv: String = current.configuration.getString("environment").getOrElse(throw new RuntimeException(s"Missing Key $env.environment"))
lazy val edhUrl: String = current.configuration.getString("endpoints.edh.url").getOrElse(throw new RuntimeException(s"Missing Key $env.edhUrl"))
}
29 changes: 21 additions & 8 deletions app/uk/gov/hmrc/rasapi/connectors/DesConnector.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package uk.gov.hmrc.rasapi.connectors

import play.api.libs.json.Writes
import uk.gov.hmrc.play.config.ServicesConfig
import uk.gov.hmrc.play.http._
import uk.gov.hmrc.play.http.logging.Authorization
Expand All @@ -27,31 +28,43 @@ import scala.concurrent.Future

trait DesConnector extends ServicesConfig {

val http: HttpGet
val httpGet: HttpGet
val httpPost: HttpPost
val desBaseUrl: String

def getResidencyStatusUrl(nino: String): String

val edhUrl: String

def getResidencyStatus(nino: Nino)(implicit hc: HeaderCarrier): Future[HttpResponse] = {

val customerNino = nino.nino
val uri = desBaseUrl + getResidencyStatusUrl(customerNino)

http.GET(uri)(httpReads, updateHeaderCarrier(hc))
httpGet.GET(uri)(implicitly[HttpReads[HttpResponse]], hc = updateHeaderCarrier(hc))
}

val httpReads: HttpReads[HttpResponse] = new HttpReads[HttpResponse] {
override def read(method: String, url: String, response: HttpResponse) = response
def sendDataToEDH(userId: String, nino: String, residencyStatus: ResidencyStatus)(implicit hc: HeaderCarrier): Future[HttpResponse] = {

httpPost.POST[EDHAudit, HttpResponse](url = edhUrl, body = EDHAudit(userId, nino, residencyStatus.currentYearResidencyStatus,
residencyStatus.nextYearForecastResidencyStatus))(implicitly[Writes[EDHAudit]], implicitly[HttpReads[HttpResponse]], updateHeaderCarrier(hc))
}


private def updateHeaderCarrier(headerCarrier: HeaderCarrier) =
headerCarrier.copy(extraHeaders = Seq(("Environment" -> AppContext.desUrlHeaderEnv)),
headerCarrier.copy(extraHeaders = Seq("Environment" -> AppContext.desUrlHeaderEnv),
authorization = Some(Authorization(s"Bearer ${AppContext.desAuthToken}")))
}

object DesConnector extends DesConnector{
object DesConnector extends DesConnector {
// $COVERAGE-OFF$Trivial and never going to be called by a test that uses it's own object implementation
override val http: HttpGet = WSHttp
override val httpGet: HttpGet = WSHttp
override val httpPost: HttpPost = WSHttp
override val desBaseUrl = baseUrl("des")
override def getResidencyStatusUrl(nino: String) = String.format(AppContext.residencyStatusUrl, nino) //"/ras-stubs/get-residency-status"

override def getResidencyStatusUrl(nino: String) = String.format(AppContext.residencyStatusUrl, nino)

//"/ras-stubs/get-residency-status"
override val edhUrl: String = desBaseUrl + AppContext.edhUrl
// $COVERAGE-ON$
}
2 changes: 1 addition & 1 deletion app/uk/gov/hmrc/rasapi/controllers/LookupController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ trait LookupController extends BaseController with HeaderValidator with RunMode
case OK =>
Logger.debug("[LookupController][getResidencyStatus] Nino returned successfully.")
val nino = customerCacheResponse.json.as[Nino]
responseHandlerService.handleResidencyStatusResponse(nino).map {
responseHandlerService.handleResidencyStatusResponse(nino, id).map {
case Left(residencyStatus) => auditResponse(failureReason = None,
nino = Some(nino.nino),
residencyStatus = Some(residencyStatus))
Expand Down
25 changes: 25 additions & 0 deletions app/uk/gov/hmrc/rasapi/models/EDHAudit.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright 2017 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.rasapi.models

import play.api.libs.json.Json

case class EDHAudit(userId: String, nino: String, currentYearResidencyStatus: String, nextYearResidencyStatus: String)

object EDHAudit {
implicit val format = Json.format[EDHAudit]
}
38 changes: 33 additions & 5 deletions app/uk/gov/hmrc/rasapi/services/HttpResponseHandlerService.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@

package uk.gov.hmrc.rasapi.services

import play.api.Logger
import play.api.libs.json.JsSuccess
import play.api.mvc.{AnyContent, Request}
import uk.gov.hmrc.play.http.HeaderCarrier
import uk.gov.hmrc.rasapi.connectors.DesConnector
import uk.gov.hmrc.rasapi.models.{Nino, ResidencyStatus, ResidencyStatusSuccess}
Expand All @@ -30,15 +32,26 @@ import scala.concurrent.ExecutionContext.Implicits.global
trait HttpResponseHandlerService {

val desConnector: DesConnector
val auditService: AuditService

def handleResidencyStatusResponse(nino: Nino)(implicit hc: HeaderCarrier) : Future[Either[ResidencyStatus, String]] = {
def handleResidencyStatusResponse(nino: Nino, userId: String)(implicit request: Request[AnyContent], hc: HeaderCarrier): Future[Either[ResidencyStatus, String]] = {

desConnector.getResidencyStatus(nino).map { response =>
Try(response.json.validate[ResidencyStatusSuccess]) match {
case Success(JsSuccess(payload, _)) =>
Left(transformResidencyStatusValues(ResidencyStatus(currentYearResidencyStatus = payload.currentYearResidencyStatus,
nextYearForecastResidencyStatus = payload.nextYearResidencyStatus)))
case _ => Right("")
val resStatus = transformResidencyStatusValues(ResidencyStatus(currentYearResidencyStatus = payload.currentYearResidencyStatus,
nextYearForecastResidencyStatus = payload.nextYearResidencyStatus))
desConnector.sendDataToEDH(userId, nino.nino, resStatus).map { httpResponse =>
auditEDHResponse(userId = userId, nino = nino.nino, auditSuccess = true)
} recover {
case _ =>
Logger.error(s"HttpResponseHandlerService - handleResidencyStatusResponse: Error returned from EDH")
auditEDHResponse(userId = userId, nino = nino.nino, auditSuccess = false)
}
Left(resStatus)
case _ =>
Logger.error(s"HttpResponseHandlerService - handleResidencyStatusResponse: Error (${response.status}) returned from Des for residency status")
Right("")
}
}
}
Expand All @@ -53,11 +66,26 @@ trait HttpResponseHandlerService {
}

ResidencyStatus(transformResidencyStatusValue(residencyStatus.currentYearResidencyStatus),
transformResidencyStatusValue(residencyStatus.nextYearForecastResidencyStatus))
transformResidencyStatusValue(residencyStatus.nextYearForecastResidencyStatus))
}


private def auditEDHResponse(userId: String, nino: String, auditSuccess: Boolean)
(implicit request: Request[AnyContent], hc: HeaderCarrier): Unit = {

val auditDataMap = Map("userId" -> userId,
"nino" -> nino,
"edhAuditSuccess" -> auditSuccess.toString)

auditService.audit(auditType = "ReliefAtSourceAudit",
path = request.path,
auditData = auditDataMap
)
}
}

object HttpResponseHandlerService extends HttpResponseHandlerService {

override val desConnector = DesConnector
override val auditService = AuditService
}
3 changes: 3 additions & 0 deletions conf/application.conf
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,9 @@ endpoints {
residency-status {
url = "/pension-scheme/customers/%s/look-up"
}
edh {
url = "/residency-lookup/audit"
}
}

desauthtoken = K1gbAD4vVreR0yoJmdd9bUp5RXwByLXfh
Expand Down
47 changes: 40 additions & 7 deletions test/uk/gov/hmrc/rasapi/connectors/DesConnectorSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

package uk.gov.hmrc.rasapi.connectors

import org.mockito.Matchers
import org.mockito.Matchers._
import org.mockito.Mockito.when
import org.scalatest.mock.MockitoSugar
import org.scalatest.{ShouldMatchers, WordSpec}
Expand All @@ -32,12 +32,15 @@ class DesConnectorSpec extends WordSpec with OneAppPerSuite with MockitoSugar wi

implicit val hc = HeaderCarrier()

val mockHttp = mock[HttpGet]
val mockHttpGet = mock[HttpGet]
val mockHttpPost = mock[HttpPost]

object TestDesConnector extends DesConnector {
override val http: HttpGet = mockHttp
override val httpGet: HttpGet = mockHttpGet
override val httpPost: HttpPost = mockHttpPost
override val desBaseUrl = ""
override def getResidencyStatusUrl(nino: String) = ""
override val edhUrl: String = "test-url"
}

val residencyStatus = Json.parse(
Expand All @@ -48,11 +51,11 @@ class DesConnectorSpec extends WordSpec with OneAppPerSuite with MockitoSugar wi
""".stripMargin
)

"DESConnector" should {
"DESConnector getResidencyStatus" should {

"handle successful response when 200 is returned from des" in {

when(mockHttp.GET[HttpResponse](Matchers.any())(Matchers.any(),Matchers.any())).
when(mockHttpGet.GET[HttpResponse](any())(any(), any())).
thenReturn(Future.successful(HttpResponse(200, Some(residencyStatus))))

val result = await(TestDesConnector.getResidencyStatus(Nino("LE241131B")))
Expand All @@ -61,7 +64,7 @@ class DesConnectorSpec extends WordSpec with OneAppPerSuite with MockitoSugar wi

"handle 404 error returned from des" in {

when(mockHttp.GET[HttpResponse](Matchers.any())(Matchers.any(),Matchers.any())).
when(mockHttpGet.GET[HttpResponse](any())(any(), any())).
thenReturn(Future.failed(new NotFoundException("")))

intercept[NotFoundException] {
Expand All @@ -71,12 +74,42 @@ class DesConnectorSpec extends WordSpec with OneAppPerSuite with MockitoSugar wi

"handle 500 error returned from des" in {

when(mockHttp.GET[HttpResponse](Matchers.any())(Matchers.any(),Matchers.any())).
when(mockHttpGet.GET[HttpResponse](any())(any(), any())).
thenReturn(Future.successful(HttpResponse(500)))

val result = TestDesConnector.getResidencyStatus(Nino("LE241131B"))
await(result).status shouldBe INTERNAL_SERVER_ERROR
}
}

"DESConnector sendDataToEDH" should {

"handle successful response when 200 is returned from EDH" in {

when(mockHttpPost.POST[EDHAudit, HttpResponse](any(), any(), any())(any(), any(), any())).
thenReturn(Future.successful(HttpResponse(200)))

val userId = "123456"
val nino = "LE241131B"
val resStatus = ResidencyStatus(currentYearResidencyStatus = "scotResident",
nextYearForecastResidencyStatus = "scotResident")

val result = await(TestDesConnector.sendDataToEDH(userId, nino, resStatus))
result.status shouldBe OK
}

"handle successful response when 500 is returned from EDH" in {
when(mockHttpPost.POST[EDHAudit, HttpResponse](any(), any(), any())(any(), any(), any())).
thenReturn(Future.successful(HttpResponse(500)))

val userId = "123456"
val nino = "LE241131B"
val resStatus = ResidencyStatus(currentYearResidencyStatus = "scotResident",
nextYearForecastResidencyStatus = "scotResident")

val result = await(TestDesConnector.sendDataToEDH(userId, nino, resStatus))
result.status shouldBe INTERNAL_SERVER_ERROR
}
}
}

14 changes: 7 additions & 7 deletions test/uk/gov/hmrc/rasapi/controllers/LookupControllerSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class LookupControllerSpec extends WordSpec with MockitoSugar with ShouldMatcher
val residencyStatus = ResidencyStatus("otherUKResident", "otherUKResident")

when(mockCachingConnector.getCachedData(any())(any())).thenReturn(Future.successful(HttpResponse(OK, Some(Json.toJson(expectedNino)))))
when(mockHttpResponseHandlerService.handleResidencyStatusResponse(any())(any())).thenReturn(Future.successful(Left(residencyStatus)))
when(mockHttpResponseHandlerService.handleResidencyStatusResponse(any(), any())(any(), any())).thenReturn(Future.successful(Left(residencyStatus)))

await(TestLookupController.getResidencyStatus(uuid)
.apply(FakeRequest(Helpers.GET, s"/relief-at-source/customer/$uuid/residency-status")
Expand Down Expand Up @@ -143,7 +143,7 @@ class LookupControllerSpec extends WordSpec with MockitoSugar with ShouldMatcher
val uuid: String = "2800a7ab-fe20-42ca-98d7-c33f4133cfc2"

when(mockCachingConnector.getCachedData(any())(any())).thenReturn(Future.successful(HttpResponse(OK, Some(Json.toJson(expectedNino)))))
when(mockHttpResponseHandlerService.handleResidencyStatusResponse(any())(any())).thenReturn(Future.successful(Right("")))
when(mockHttpResponseHandlerService.handleResidencyStatusResponse(any(), any())(any(), any())).thenReturn(Future.successful(Right("")))

await(TestLookupController.getResidencyStatus(uuid)
.apply(FakeRequest(Helpers.GET, s"/relief-at-source/customer/$uuid/residency-status")
Expand All @@ -165,7 +165,7 @@ class LookupControllerSpec extends WordSpec with MockitoSugar with ShouldMatcher
val uuid: String = "2800a7ab-fe20-42ca-98d7-c33f4133cfc2"

when(mockCachingConnector.getCachedData(any())(any())).thenReturn(Future.successful(HttpResponse(OK, Some(Json.toJson(expectedNino)))))
when(mockHttpResponseHandlerService.handleResidencyStatusResponse(any())(any())).thenReturn(Future.successful(Right("")))
when(mockHttpResponseHandlerService.handleResidencyStatusResponse(any(), any())(any(), any())).thenReturn(Future.successful(Right("")))

await(TestLookupController.getResidencyStatus(uuid)
.apply(FakeRequest(Helpers.GET, s"/relief-at-source/customer/$uuid/residency-status")
Expand All @@ -187,7 +187,7 @@ class LookupControllerSpec extends WordSpec with MockitoSugar with ShouldMatcher
val uuid: String = "2800a7ab-fe20-42ca-98d7-c33f4133cfc2"

when(mockCachingConnector.getCachedData(any())(any())).thenReturn(Future.successful(HttpResponse(OK, Some(Json.toJson(expectedNino)))))
when(mockHttpResponseHandlerService.handleResidencyStatusResponse(any())(any())).thenReturn(Future.successful(Right("")))
when(mockHttpResponseHandlerService.handleResidencyStatusResponse(any(), any())(any(), any())).thenReturn(Future.successful(Right("")))

await(TestLookupController.getResidencyStatus(uuid)
.apply(FakeRequest(Helpers.GET, s"/relief-at-source/customer/$uuid/residency-status")
Expand All @@ -209,7 +209,7 @@ class LookupControllerSpec extends WordSpec with MockitoSugar with ShouldMatcher
val uuid: String = "2800a7ab-fe20-42ca-98d7-c33f4133cfc2"

when(mockCachingConnector.getCachedData(any())(any())).thenReturn(Future.successful(HttpResponse(OK, Some(Json.toJson(expectedNino)))))
when(mockHttpResponseHandlerService.handleResidencyStatusResponse(any())(any())).thenReturn(Future.successful(Right("")))
when(mockHttpResponseHandlerService.handleResidencyStatusResponse(any(), any())(any(), any())).thenReturn(Future.successful(Right("")))

await(TestLookupController.getResidencyStatus(uuid)
.apply(FakeRequest(Helpers.GET, s"/relief-at-source/customer/$uuid/residency-status")
Expand Down Expand Up @@ -246,7 +246,7 @@ class LookupControllerSpec extends WordSpec with MockitoSugar with ShouldMatcher
""".stripMargin)

when(mockCachingConnector.getCachedData(any())(any())).thenReturn(Future.successful(HttpResponse(OK, Some(Json.toJson(expectedNino)))))
when(mockHttpResponseHandlerService.handleResidencyStatusResponse(any())(any())).thenReturn(Future.successful(Left(residencyStatus)))
when(mockHttpResponseHandlerService.handleResidencyStatusResponse(any(), any())(any(), any())).thenReturn(Future.successful(Left(residencyStatus)))

val result = TestLookupController.getResidencyStatus(uuid).apply(FakeRequest(Helpers.GET, "/").withHeaders(acceptHeader))

Expand Down Expand Up @@ -458,7 +458,7 @@ class LookupControllerSpec extends WordSpec with MockitoSugar with ShouldMatcher
""".stripMargin)

when(mockCachingConnector.getCachedData(any())(any())).thenReturn(Future.successful(HttpResponse(OK, Some(Json.toJson(expectedNino)))))
when(mockHttpResponseHandlerService.handleResidencyStatusResponse(any())(any())).thenReturn(Future.successful(Right("")))
when(mockHttpResponseHandlerService.handleResidencyStatusResponse(any(), any())(any(), any())).thenReturn(Future.successful(Right("")))

val result = TestLookupController.getResidencyStatus(uuid).apply(FakeRequest(Helpers.GET, "/").withHeaders(acceptHeader))

Expand Down
Loading

0 comments on commit 0883ace

Please sign in to comment.