diff --git a/app/controllers/verify/VerificationNotSubmittedWarningController.scala b/app/controllers/verify/VerificationNotSubmittedWarningController.scala new file mode 100644 index 00000000..54f99f57 --- /dev/null +++ b/app/controllers/verify/VerificationNotSubmittedWarningController.scala @@ -0,0 +1,50 @@ +/* + * Copyright 2026 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 controllers.verify + +import config.FrontendAppConfig +import controllers.actions.* +import play.api.i18n.{I18nSupport, MessagesApi} +import play.api.mvc.{Action, AnyContent, MessagesControllerComponents} +import queries.CisIdQuery +import uk.gov.hmrc.play.bootstrap.frontend.controller.FrontendBaseController +import views.html.verify.VerificationNotSubmittedWarningView + +import javax.inject.Inject + +class VerificationNotSubmittedWarningController @Inject() ( + override val messagesApi: MessagesApi, + identify: IdentifierAction, + getData: DataRetrievalAction, + requireData: DataRequiredAction, + val controllerComponents: MessagesControllerComponents, + view: VerificationNotSubmittedWarningView, + appConfig: FrontendAppConfig +) extends FrontendBaseController + with I18nSupport { + + def onPageLoad: Action[AnyContent] = (identify andThen getData andThen requireData) { implicit request => + request.userAnswers.get(CisIdQuery) match { + case Some(cisId) => + val manageSubcontractorsUrl = s"${appConfig.manageSubcontractorsUrl}/$cisId" + Ok(view(manageSubcontractorsUrl, appConfig.cisGeneralEnquiries)) + + case None => + Redirect(controllers.routes.JourneyRecoveryController.onPageLoad()) + } + } +} diff --git a/app/views/verify/VerificationNotSubmittedWarningView.scala.html b/app/views/verify/VerificationNotSubmittedWarningView.scala.html new file mode 100644 index 00000000..a594381b --- /dev/null +++ b/app/views/verify/VerificationNotSubmittedWarningView.scala.html @@ -0,0 +1,42 @@ +@* + * Copyright 2026 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. + *@ + +@import views.html.components._ + +@this( + layout: templates.Layout, + heading: H1, + link: Link +) + +@(manageSubcontractorsUrl: String, contactHmrcUrl: String)(implicit request: Request[_], messages: Messages) + +@layout(pageTitle = titleNoForm(messages("verify.verificationNotSubmittedWarning.title")), showBackLink = false) { + + @heading(messages("verify.verificationNotSubmittedWarning.heading")) + @link( + "verify.verificationNotSubmittedWarning.link1.text", + contactHmrcUrl, + prefixTextKey = "verify.verificationNotSubmittedWarning.link1.prefix", + suffixTextKey = "verify.verificationNotSubmittedWarning.link1.suffix" + ) + @link( + "verify.verificationNotSubmittedWarning.link2.text", + manageSubcontractorsUrl, + prefixTextKey = "verify.verificationNotSubmittedWarning.link2.prefix", + hasFullStop = true + ) +} diff --git a/conf/app.routes b/conf/app.routes index 6e43525d..5afbd9f4 100644 --- a/conf/app.routes +++ b/conf/app.routes @@ -400,3 +400,5 @@ POST /verify/no-new-subcontractors-to-verify controllers.verify.Verify GET /verify/problem-with-verification-warning controllers.verify.VerifyDepartmentalErrorController.onPageLoad() GET /verify/inactive-scheme-warning controllers.verify.InactiveSchemeWarningController.onPageLoad() + +GET /verify/verification-not-submitted-warning controllers.verify.VerificationNotSubmittedWarningController.onPageLoad() diff --git a/conf/messages.en b/conf/messages.en index 3a4ac49b..774fceb1 100644 --- a/conf/messages.en +++ b/conf/messages.en @@ -898,3 +898,11 @@ verify.inactiveSchemeWarning.p1 = Your scheme verify.inactiveSchemeWarning.p2 = You must contact HMRC by phone to reactivate your scheme before you can pay any more subcontractors. verify.inactiveSchemeWarning.warningText = Any verification request that you send while your scheme is inactive will fail when you try to submit it. verify.inactiveSchemeWarning.cancel = Cancel request + +verify.verificationNotSubmittedWarning.title = Your verification request cannot be submitted +verify.verificationNotSubmittedWarning.heading = Your verification request cannot be submitted +verify.verificationNotSubmittedWarning.link1.prefix = You must +verify.verificationNotSubmittedWarning.link1.text = contact HMRC +verify.verificationNotSubmittedWarning.link1.suffix = for more help. +verify.verificationNotSubmittedWarning.link2.text = Manage your subcontractors +verify.verificationNotSubmittedWarning.link2.prefix = Back to diff --git a/test/controllers/verify/VerificationNotSubmittedWarningControllerSpec.scala b/test/controllers/verify/VerificationNotSubmittedWarningControllerSpec.scala new file mode 100644 index 00000000..0325884d --- /dev/null +++ b/test/controllers/verify/VerificationNotSubmittedWarningControllerSpec.scala @@ -0,0 +1,91 @@ +/* + * Copyright 2026 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 controllers.verify + +import base.SpecBase +import models.UserAnswers +import org.scalatest.matchers.must.Matchers +import play.api.http.Status +import play.api.test.FakeRequest +import play.api.test.Helpers._ +import queries.CisIdQuery +import views.html.verify.VerificationNotSubmittedWarningView + +class VerificationNotSubmittedWarningControllerSpec extends SpecBase with Matchers { + + private val cisId = "1234" + + "VerificationNotSubmittedWarningController" - { + + "must return OK and render the correct view when CisId is present" in { + + val userAnswers = + UserAnswers(userAnswersId) + .set(CisIdQuery, cisId) + .success + .value + + val application = + applicationBuilder(userAnswers = Some(userAnswers)).build() + + running(application) { + + val request = + FakeRequest( + GET, + routes.VerificationNotSubmittedWarningController.onPageLoad().url + ) + + val result = route(application, request).value + + val view = + application.injector.instanceOf[VerificationNotSubmittedWarningView] + + val expectedManageSubcontractorsUrl = + s"${applicationConfig.manageSubcontractorsUrl}/$cisId" + + status(result) mustBe Status.OK + contentAsString(result) mustBe + view( + expectedManageSubcontractorsUrl, + applicationConfig.cisGeneralEnquiries + )(request, messages(application)).toString + } + } + + "must redirect to Journey Recovery when CisId is missing" in { + + val application = + applicationBuilder(userAnswers = Some(emptyUserAnswers)).build() + + running(application) { + + val request = + FakeRequest( + GET, + routes.VerificationNotSubmittedWarningController.onPageLoad().url + ) + + val result = route(application, request).value + + status(result) mustBe Status.SEE_OTHER + redirectLocation(result).value mustBe + controllers.routes.JourneyRecoveryController.onPageLoad().url + } + } + } +} diff --git a/test/views/verify/VerificationNotSubmittedWarningViewSpec.scala b/test/views/verify/VerificationNotSubmittedWarningViewSpec.scala new file mode 100644 index 00000000..ec61a47e --- /dev/null +++ b/test/views/verify/VerificationNotSubmittedWarningViewSpec.scala @@ -0,0 +1,97 @@ +/* + * Copyright 2026 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 views.verify + +import config.FrontendAppConfig +import org.jsoup.Jsoup +import org.scalatest.matchers.must.Matchers +import org.scalatest.wordspec.AnyWordSpec +import org.scalatestplus.play.guice.GuiceOneAppPerSuite +import play.api.i18n.{Lang, Messages, MessagesApi, MessagesImpl} +import play.api.mvc.Request +import play.api.test.FakeRequest +import views.html.verify.VerificationNotSubmittedWarningView + +class VerificationNotSubmittedWarningViewSpec extends AnyWordSpec with Matchers with GuiceOneAppPerSuite { + + implicit val request: Request[_] = + FakeRequest() + + implicit val messages: Messages = + MessagesImpl( + Lang.defaultLang, + app.injector.instanceOf[MessagesApi] + ) + + implicit val appConfig: FrontendAppConfig = + app.injector.instanceOf[FrontendAppConfig] + + private val view: VerificationNotSubmittedWarningView = + app.injector.instanceOf[VerificationNotSubmittedWarningView] + + "VerificationNotSubmittedWarningView" should { + + "render the page with correct title, heading and both links" in { + + val manageSubcontractorsUrl = "/manage-subcontractors/T1234567" + val contactHmrcUrl = "https://www.gov.uk/contact-hmrc" + + val html = + view(manageSubcontractorsUrl, contactHmrcUrl)( + request, + messages + ) + + val doc = Jsoup.parse(html.toString()) + + doc.select("title").text() must include( + messages("verify.verificationNotSubmittedWarning.title") + ) + + doc.select("h1").size() mustBe 1 + doc.select("h1").text() mustBe + messages("verify.verificationNotSubmittedWarning.heading") + + val firstLink = + doc.select(s"a[href='$contactHmrcUrl']") + firstLink.size() mustBe 1 + firstLink.text() mustBe + messages("verify.verificationNotSubmittedWarning.link1.text") + + val firstLinkText = firstLink.first().parent().text() + firstLinkText must include( + messages("verify.verificationNotSubmittedWarning.link1.suffix") + ) + firstLinkText must include( + messages("verify.verificationNotSubmittedWarning.link1.prefix") + ) + firstLinkText.trim.endsWith(".") mustBe true + + val secondLink = + doc.select(s"a[href='$manageSubcontractorsUrl']") + secondLink.size() mustBe 1 + secondLink.text() mustBe + messages("verify.verificationNotSubmittedWarning.link2.text") + + val secondLinkText = secondLink.first().parent().text() + secondLinkText must include( + messages("verify.verificationNotSubmittedWarning.link2.prefix") + ) + secondLinkText.trim.endsWith(".") mustBe true + } + } +}