From 89bb433ba82df8c7abf583fd4e319e74dde2db7e Mon Sep 17 00:00:00 2001 From: PavelVjalicin <pavelvjalicin@users.noreply.github.com> Date: Tue, 30 Jul 2024 10:05:34 +0100 Subject: [PATCH 1/3] PODS-9128: Exception handling --- app/controllers/address/ChooseAddressController.scala | 2 +- .../fileUpload/FileUploadResultController.scala | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/app/controllers/address/ChooseAddressController.scala b/app/controllers/address/ChooseAddressController.scala index 2d251a9de..f5ecc3b80 100644 --- a/app/controllers/address/ChooseAddressController.scala +++ b/app/controllers/address/ChooseAddressController.scala @@ -53,7 +53,7 @@ class ChooseAddressController @Inject()(val controllerComponents: MessagesContro addresses, index )) - case _ => Redirect(controllers.routes.JourneyRecoveryController.onPageLoad(None).url) + case _ => throw new RuntimeException("User answers not available") } } diff --git a/app/controllers/fileUpload/FileUploadResultController.scala b/app/controllers/fileUpload/FileUploadResultController.scala index 53c4b169b..23cd6066e 100644 --- a/app/controllers/fileUpload/FileUploadResultController.scala +++ b/app/controllers/fileUpload/FileUploadResultController.scala @@ -112,14 +112,15 @@ class FileUploadResultController @Inject()(val controllerComponents: MessagesCon val originalUserAnswers = request.userAnswers.fold(UserAnswers())(identity) val updatedAnswers = originalUserAnswers.setOrException(FileUploadResultPage(eventType), value) val redirectResultPage: Result = Redirect(FileUploadResultPage(eventType).navigate(waypoints, originalUserAnswers, updatedAnswers).route) - userAnswersCacheConnector.save(request.pstr, eventType, updatedAnswers).map { _ => + userAnswersCacheConnector.save(request.pstr, eventType, updatedAnswers).flatMap { _ => if (value == FileUploadResult.Yes) { parsingAndValidationOutcomeCacheConnector .deleteOutcome .flatMap(_ => asyncGetUpscanFileAndParse(eventType)) - redirectResultPage + .map(_ => redirectResultPage) + } else { - redirectResultPage + Future.successful(redirectResultPage) } } } @@ -213,8 +214,8 @@ class FileUploadResultController @Inject()(val controllerComponents: MessagesCon sendUpscanFileDownloadAuditEvent(eventType, httpResponse.status, startTime, fileUploadOutcomeResponse) httpResponse.status match { case OK => performValidation(eventType, httpResponse.bodyAsSource, fileName) recoverWith { - case e: Throwable => - setGeneralErrorOutcome("Unable to download file", fileName, Some(e)) + case e => + throw new RuntimeException("Unable to download file", e) //TODO: Might need to handle this in error handler. } case e => setGeneralErrorOutcome(s"Upscan download error response code $e", fileName) From 3c3c5ccdd24f8c09d8214acbd0fec722953873c2 Mon Sep 17 00:00:00 2001 From: PavelVjalicin <pavelvjalicin@users.noreply.github.com> Date: Mon, 5 Aug 2024 20:04:38 +0100 Subject: [PATCH 2/3] PODS-9128 --- app/handlers/ErrorHandler.scala | 12 +++++++--- app/views/UserLockedView.scala.html | 37 +++++++++++++++++++++++++++++ conf/messages.en | 2 ++ 3 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 app/views/UserLockedView.scala.html diff --git a/app/handlers/ErrorHandler.scala b/app/handlers/ErrorHandler.scala index af066ecfe..665b53adb 100644 --- a/app/handlers/ErrorHandler.scala +++ b/app/handlers/ErrorHandler.scala @@ -17,12 +17,14 @@ package handlers import config.FrontendAppConfig +import play.api.Logging import play.api.i18n.{I18nSupport, MessagesApi} import play.api.mvc.Results.{Ok, Redirect} -import play.api.mvc.{Request, RequestHeader, Result} +import play.api.mvc.{Request, RequestHeader, Result, Results} import play.twirl.api.Html +import uk.gov.hmrc.http.HttpException import uk.gov.hmrc.play.bootstrap.frontend.http.FrontendErrorHandler -import views.html.{ErrorTemplate, NoDataEnteredErrorView, PageNotFoundErrorView} +import views.html.{ErrorTemplate, NoDataEnteredErrorView, PageNotFoundErrorView, UserLockedView} import javax.inject.{Inject, Singleton} import scala.concurrent.Future @@ -33,8 +35,9 @@ class ErrorHandler @Inject()( view: ErrorTemplate, noDataEnteredView: NoDataEnteredErrorView, pageNotFoundView: PageNotFoundErrorView, + userLockedView: UserLockedView, config: FrontendAppConfig - ) extends FrontendErrorHandler with I18nSupport { + ) extends FrontendErrorHandler with I18nSupport with Logging { override def standardErrorTemplate(pageTitle: String, heading: String, message: String)(implicit rh: Request[_]): Html = view(pageTitle, heading, message) @@ -44,6 +47,9 @@ class ErrorHandler @Inject()( override def onServerError(request: RequestHeader, exception: Throwable): Future[Result] = { exception match { + case e: HttpException if e.message.contains("EVENT_LOCKED") => + logger.warn("User is locked on " + request.uri) + Future.successful(new Results.Status(e.responseCode)(userLockedView(config.contactHmrcURL)(Request(request, ""), request2Messages(request)))) case _ : TaxYearNotAvailableException => Future.successful(Redirect(config.yourPensionSchemesUrl)) case _: NothingToSubmitException => diff --git a/app/views/UserLockedView.scala.html b/app/views/UserLockedView.scala.html new file mode 100644 index 000000000..6d90fcd81 --- /dev/null +++ b/app/views/UserLockedView.scala.html @@ -0,0 +1,37 @@ +@* + * 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. + *@ + +@this( + layout: templates.Layout +) + +@(contactHmrcUrl: String)(implicit request: Request[_], messages: Messages) + +@layout( + pageTitle = titleNoForm(messages("userLocked.text")), + showBackLink = false +) { + + <h1 class="govuk-heading-xl">@messages("userLocked.text")</h1> + <p class="govuk-body"> + @messages("pageNotFound404.p3") + <a href="@contactHmrcUrl" class="govuk-link"> + @messages("pageNotFound404.p4") + </a> + </p> + +} + diff --git a/conf/messages.en b/conf/messages.en index 384141bcc..dd52a8639 100644 --- a/conf/messages.en +++ b/conf/messages.en @@ -1850,6 +1850,8 @@ pageNotFound404.p2 = If you pasted the web address, check you copied the entire pageNotFound404.p3 = If the web address is correct or you selected a link or button, pageNotFound404.p4 = contact HMRC. +userLocked.text = Event is locked by a user + cannotResume.title = This event report cannot be submitted cannotResume.heading = This event report cannot be submitted cannotResume.p1 = You have attempted to amend or create an event report but no changes have been made. From 3dd6c6e51de3bf75279baba1ae7c1635081bbc9c Mon Sep 17 00:00:00 2001 From: PavelVjalicin <pavelvjalicin@users.noreply.github.com> Date: Tue, 6 Aug 2024 12:44:24 +0100 Subject: [PATCH 3/3] PODS-9128: fixed tests --- .../fileUpload/FileUploadResultControllerSpec.scala | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/test/controllers/fileUpload/FileUploadResultControllerSpec.scala b/test/controllers/fileUpload/FileUploadResultControllerSpec.scala index e20593ab2..6261a412f 100644 --- a/test/controllers/fileUpload/FileUploadResultControllerSpec.scala +++ b/test/controllers/fileUpload/FileUploadResultControllerSpec.scala @@ -17,7 +17,7 @@ package controllers.fileUpload import base.SpecBase -import connectors.{EventReportingConnector, UserAnswersCacheConnector} +import connectors.{EventReportingConnector, ParsingAndValidationOutcomeCacheConnector, UserAnswersCacheConnector} import forms.fileUpload.FileUploadResultFormProvider import models.FileUploadOutcomeResponse import models.FileUploadOutcomeStatus.{FAILURE, IN_PROGRESS, SUCCESS} @@ -51,10 +51,12 @@ class FileUploadResultControllerSpec extends SpecBase with BeforeAndAfterEach { private val mockUserAnswersCacheConnector = mock[UserAnswersCacheConnector] private val mockERConnector = mock[EventReportingConnector] + private val mockParsingAndValidationOutcomeCacheConnector = mock[ParsingAndValidationOutcomeCacheConnector] private val extraModules: Seq[GuiceableModule] = Seq[GuiceableModule]( bind[UserAnswersCacheConnector].toInstance(mockUserAnswersCacheConnector), - bind[EventReportingConnector].toInstance(mockERConnector) + bind[EventReportingConnector].toInstance(mockERConnector), + bind[ParsingAndValidationOutcomeCacheConnector].toInstance(mockParsingAndValidationOutcomeCacheConnector) ) private def getRoute(eventType: EventType): String = routes.FileUploadResultController.onPageLoad(waypoints, eventType).url @@ -63,8 +65,11 @@ class FileUploadResultControllerSpec extends SpecBase with BeforeAndAfterEach { override def beforeEach(): Unit = { super.beforeEach() + reset(mockParsingAndValidationOutcomeCacheConnector) reset(mockUserAnswersCacheConnector) reset(mockERConnector) + when(mockParsingAndValidationOutcomeCacheConnector.deleteOutcome(any(), any())).thenReturn(Future.successful()) + when(mockParsingAndValidationOutcomeCacheConnector.setOutcome(any())(any(), any())).thenReturn(Future.successful()) } "FileUploadResult Controller" - {