Repository: hmrc/gform-frontend
Pull request #2462: GFORMS-3341 - Language switch not working on download pdf/continue pages
Author: login: cmanson
Created: 2025-04-15T15:02:31Z | Merged: 2025-04-17T16:28:28Z



Diff:
diff --git a/app/uk/gov/hmrc/gform/gform/NewFormController.scala b/app/uk/gov/hmrc/gform/gform/NewFormController.scala
index 24d92dda00..5f533b6ac9 100644
--- a/app/uk/gov/hmrc/gform/gform/NewFormController.scala
+++ b/app/uk/gov/hmrc/gform/gform/NewFormController.scala
@@ -82,7 +82,7 @@ class NewFormController(
   private def formTemplateIdCookie(formTemplateId: FormTemplateId) =
     Cookie(formTemplateIdCookieName, formTemplateId.value, secure = true)
 
-  def dashboard(formTemplateId: FormTemplateId) =
+  def dashboard(formTemplateId: FormTemplateId, se: SuppressErrors) =
     auth.authWithOptReferrerCheckWithoutRetrievingForm(
       formTemplateId,
       OperationWithoutForm.ViewDashboard
@@ -91,9 +91,9 @@ class NewFormController(
 
       def checkDraftRetrievalMethod(draftRetrievalMethod: DraftRetrievalMethod) =
         (draftRetrievalMethod, cache.retrievals) match {
-          case (BySubmissionReference, _) => showAccesCodePage(cache, cache.formTemplate)
+          case (BySubmissionReference, _) => showAccesCodePage(cache, cache.formTemplate, se)
           case (FormAccessCodeForAgents(_), IsAgent()) | (FormAccessCode(_), _) =>
-            exitPageHandler(cache, showAccesCodePage)
+            exitPageHandler(cache, se, showAccesCodePage)
           case _ =>
             Redirect(routes.NewFormController.newOrContinue(formTemplateId).url, request.queryString).pure[Future]
         }
@@ -154,7 +154,7 @@ class NewFormController(
     *
     * It will try to load form without accessCode and only if such a form doesn't exists present user with Access Code page
     */
-  private def showAccesCodePage(cache: AuthCacheWithoutForm, formTemplate: FormTemplate)(implicit
+  private def showAccesCodePage(cache: AuthCacheWithoutForm, formTemplate: FormTemplate, se: SuppressErrors)(implicit
     request: Request[AnyContent],
     l: LangADT
   ) = {
@@ -172,7 +172,13 @@ class NewFormController(
       draftRetrievalMethod match {
         case BySubmissionReference => showAccessCodeList(cache, userId, formTemplateId)
         case _ =>
-          val accessCodeStart = new AccessCodeStart(cache.formTemplate, AccessCodePage.decision, frontendConfig)
+          val accessCodeStart = AccessCodePage.decision
+            .bindFromRequest()
+            .fold(
+              errors => new AccessCodeStart(cache.formTemplate, errors, frontendConfig, se),
+              _ => new AccessCodeStart(cache.formTemplate, AccessCodePage.decision, frontendConfig, se)
+            )
+
           def switchLanguageForAgentCodeStart: (FormTemplateId, Option[AccessCode], String) => Call =
             (formTemplateId: FormTemplateId, maybeAccessCode: Option[AccessCode], lang: String) =>
               uk.gov.hmrc.gform.gform.routes.LanguageSwitchController
@@ -358,7 +364,7 @@ class NewFormController(
         newForm(formTemplateId, cache, QueryParams.empty)
     }
 
-  def continue(cache: AuthCacheWithoutForm, formTemplate: FormTemplate)(implicit
+  def continue(cache: AuthCacheWithoutForm, formTemplate: FormTemplate, se: SuppressErrors)(implicit
     request: Request[AnyContent],
     lang: LangADT
   ): Future[Result] = {
@@ -426,7 +432,7 @@ class NewFormController(
   def newOrContinue(formTemplateId: FormTemplateId): Action[AnyContent] =
     auth.authWithoutRetrievingForm(formTemplateId, OperationWithoutForm.EditForm) {
       implicit request => implicit l => cache =>
-        exitPageHandler(cache, continue)
+        exitPageHandler(cache, SuppressErrors.Yes, continue)
     }
 
   private val startNewOrLogout: data.Form[String] = play.api.data.Form(
@@ -575,24 +581,40 @@ class NewFormController(
                .pure[Future]
     } yield res
 
-  def accessCodeDownload(formTemplateId: FormTemplateId): Action[AnyContent] =
-    accessCode(formTemplateId, isContinue = false)
+  def accessCodeDownload(formTemplateId: FormTemplateId, se: SuppressErrors): Action[AnyContent] =
+    accessCode(formTemplateId, se, isContinue = false)
+
+  def accessCodeRetrieveForm(formTemplateId: FormTemplateId, se: SuppressErrors): Action[AnyContent] =
+    accessCode(formTemplateId, se, isContinue = true)
 
-  def accessCodeRetrieveForm(formTemplateId: FormTemplateId): Action[AnyContent] =
-    accessCode(formTemplateId, isContinue = true)
+  private val notFoundParm = QueryParam("nf")
 
-  private def accessCode(formTemplateId: FormTemplateId, isContinue: Boolean): Action[AnyContent] =
+  private def accessCode(formTemplateId: FormTemplateId, se: SuppressErrors, isContinue: Boolean): Action[AnyContent] =
     auth.authWithoutRetrievingForm(formTemplateId, OperationWithoutForm.EditForm) {
       implicit request => implicit lang => cache =>
         for {
           (newCache, drm) <- getDraftRetrievalMethod(cache)
           res <- {
-            val formAccessEnter =
-              new AccessCodeEnter(newCache.formTemplate, AccessCodePage.form(drm), isContinue)
+            val queryParams: QueryParams = QueryParams.fromRequest(request)
+            val notFound: Boolean = queryParams.params.getOrElse(notFoundParm, QueryParamValue("false")).value.toBoolean
+            val firstBindForm: data.Form[AccessCodeForm] = AccessCodePage.form(drm).bindFromRequest()
+            val accessCodeForm: data.Form[AccessCodeForm] =
+              if (notFound) firstBindForm.withError(AccessCodePage.key, "error.notfound") else firstBindForm
+
+            val accessCodeEnter: AccessCodeEnter = accessCodeForm
+              .fold(
+                errorForm => new AccessCodeEnter(newCache.formTemplate, errorForm, isContinue, se),
+                _ => new AccessCodeEnter(newCache.formTemplate, AccessCodePage.form(drm), isContinue, se)
+              )
+            def switchLanguageForAgentCodeStart: (FormTemplateId, Option[AccessCode], String) => Call =
+              (formTemplateId: FormTemplateId, maybeAccessCode: Option[AccessCode], lang: String) =>
+                uk.gov.hmrc.gform.gform.routes.LanguageSwitchController
+                  .switchToLanguageNoDataChange(lang)
+
             Ok(
               access_code_enter(
-                frontendAppConfig,
-                formAccessEnter,
+                frontendAppConfig.copy(routeToSwitchLanguageDataChange = switchLanguageForAgentCodeStart),
+                accessCodeEnter,
                 routes.NewFormController.dashboard(formTemplateId)
               )
             ).pure[Future]
@@ -602,46 +624,49 @@ class NewFormController(
     }
 
   def accessCodePost(formTemplateId: FormTemplateId): Action[AnyContent] = {
-    def badRequest(formTemplate: FormTemplate, errors: play.api.data.Form[AccessCodeForm])(implicit
-      request: Request[AnyContent],
-      lang: LangADT
+    def badRequest(errorForm: play.api.data.Form[AccessCodeForm], notFound: Boolean = false)(implicit
+      request: Request[AnyContent]
     ) = {
-      val isContinue = errors.data.getOrElse(AccessCodePage.isContinueKey, "false") == "true"
-      val formAccessEnter = new AccessCodeEnter(formTemplate, errors, isContinue)
-      BadRequest(
-        access_code_enter(
-          frontendAppConfig,
-          formAccessEnter,
-          routes.NewFormController.dashboard(formTemplateId)
-        )
+      val isContinue = errorForm.data.getOrElse(AccessCodePage.isContinueKey, "false") == "true"
+
+      val queryParams: QueryParams = QueryParams.fromRequest(request) + (
+        QueryParam(AccessCodePage.key) -> QueryParamValue(errorForm.data.getOrElse(AccessCodePage.key, "")),
+        notFoundParm                   -> QueryParamValue(notFound.toString)
       )
+
+      val url =
+        if (isContinue) routes.NewFormController.accessCodeRetrieveForm(formTemplateId, SuppressErrors.No).url
+        else routes.NewFormController.accessCodeDownload(formTemplateId, SuppressErrors.No).url
+
+      Redirect(
+        url,
+        queryParams.toPlayQueryParams
+      ).pure[Future]
     }
 
-    def notFound(formTemplate: FormTemplate)(implicit request: Request[AnyContent], lang: LangADT) =
+    def notFound(drm: DraftRetrievalMethod)(implicit request: Request[AnyContent]) =
       badRequest(
-        formTemplate,
         AccessCodePage
-          .form(formTemplate.draftRetrievalMethod)
-          .bindFromRequest()
-          .withError(AccessCodePage.key, "error.notfound")
+          .form(drm)
+          .bindFromRequest(),
+        notFound = true
       )
 
-    def optionAccess(access: String, cache: AuthCacheWithoutForm)(implicit
+    def optionAccess(drm: DraftRetrievalMethod, access: String, cache: AuthCacheWithoutForm)(implicit
       hc: HeaderCarrier,
       request: Request[AnyContent],
       lang: LangADT
     ) = {
       val accessCode: AccessCode = AccessCode(access)
       val formIdData = FormIdData.WithAccessCode(UserId(cache.retrievals), formTemplateId, accessCode)
-      handleForm(formIdData, cache.formTemplate)(notFound(cache.formTemplate).pure[Future]) { form =>
+      handleForm(formIdData, cache.formTemplate)(notFound(drm)) { form =>
         redirectContinue[SectionSelectorType.Normal](cache, form, Some(accessCode), request)
       }
     }
 
-    def optionDownload(access: String, cache: AuthCacheWithoutForm)(implicit
+    def optionDownload(drm: DraftRetrievalMethod, access: String, cache: AuthCacheWithoutForm)(implicit
       hc: HeaderCarrier,
-      request: Request[AnyContent],
-      lang: LangADT
+      request: Request[AnyContent]
     ) = {
       val accessCode: AccessCode = AccessCode(access)
       for {
@@ -652,7 +677,7 @@ class NewFormController(
         maybeForm <- gformConnector.maybeForm(formIdData, cache.formTemplate)
         res <- maybeForm
                  .filter(_.status === Submitted)
-                 .fold(notFound(cache.formTemplate).pure[Future]) { _ =>
+                 .fold(notFound(drm)) { _ =>
                    Redirect(
                      routes.NewFormController
                        .lastSubmission(cache.formTemplate._id, Some(accessCode), SuppressErrors.Yes)
@@ -669,11 +694,11 @@ class NewFormController(
         .form(drm)
         .bindFromRequest()
         .fold(
-          (hasErrors: data.Form[AccessCodeForm]) => Future.successful(badRequest(cache.formTemplate, hasErrors)),
+          errorsForm => badRequest(errorsForm),
           accessCodeForm =>
             accessCodeForm.isContinue match {
-              case "true"  => optionAccess(accessCodeForm.accessCode, cache)
-              case "false" => optionDownload(accessCodeForm.accessCode, cache)
+              case "true"  => optionAccess(drm, accessCodeForm.accessCode, cache)
+              case "false" => optionDownload(drm, accessCodeForm.accessCode, cache)
               case otherwise =>
                 Future.failed(
                   new Exception(
@@ -722,22 +747,19 @@ class NewFormController(
   }
 
   def newFormPost(formTemplateId: FormTemplateId): Action[AnyContent] = {
-    def badRequest(formTemplate: FormTemplate, errors: play.api.data.Form[String])(implicit
-      request: Request[AnyContent],
-      lang: LangADT
-    ) = {
-      val accessCodeStart = new AccessCodeStart(formTemplate, errors, frontendConfig)
-      BadRequest(access_code_start(frontendAppConfig, accessCodeStart))
-    }
-
     def processSubmittedData(cache: AuthCacheWithoutForm, drm: DraftRetrievalMethod)(implicit
-      request: Request[AnyContent],
-      l: LangADT
-    ): Future[Result] =
+      request: Request[AnyContent]
+    ): Future[Result] = {
+      val queryParams: QueryParams = QueryParams.fromRequest(request)
       AccessCodePage.decision
         .bindFromRequest()
         .fold(
-          (hasErrors: data.Form[String]) => Future.successful(badRequest(cache.formTemplate, hasErrors)),
+          errors =>
+            Redirect(
+              routes.NewFormController.dashboard(formTemplateId, SuppressErrors.No).url,
+              queryParams.toPlayQueryParams
+            )
+              .pure[Future],
           {
             case AccessCodePage.optionNew => processNewForm(cache, drm)
             case AccessCodePage.optionDownload =>
@@ -752,13 +774,13 @@ class NewFormController(
               )
           }
         )
+    }
 
-    auth.authWithoutRetrievingForm(formTemplateId, OperationWithoutForm.EditForm) {
-      implicit request => implicit lang => cache =>
-        for {
-          (newCache, drm) <- getDraftRetrievalMethod(cache)
-          res             <- processSubmittedData(newCache, drm)
-        } yield res
+    auth.authWithoutRetrievingForm(formTemplateId, OperationWithoutForm.EditForm) { implicit request => lang => cache =>
+      for {
+        (newCache, drm) <- getDraftRetrievalMethod(cache)
+        res             <- processSubmittedData(newCache, drm)
+      } yield res
     }
   }
 
@@ -849,7 +871,8 @@ class NewFormController(
 
   private def exitPageHandler(
     cache: AuthCacheWithoutForm,
-    continue: (AuthCacheWithoutForm, FormTemplate) => Future[Result]
+    se: SuppressErrors,
+    continue: (AuthCacheWithoutForm, FormTemplate, SuppressErrors) => Future[Result]
   )(implicit
     request: Request[AnyContent],
     l: LangADT
@@ -881,7 +904,7 @@ class NewFormController(
           }
         }
 
-        maybeExitPage.fold(continue(newCache, formTemplate)) { exitPage =>
+        maybeExitPage.fold(continue(newCache, formTemplate, se)) { exitPage =>
           implicit val sse = (new RealSmartStringEvaluatorFactory(englishMessages)).noForm(
             initFormEvaluator.evalExpr
           )
diff --git a/app/uk/gov/hmrc/gform/testonly/TestOnlyController.scala b/app/uk/gov/hmrc/gform/testonly/TestOnlyController.scala
index 69e46cf636..79faf985e2 100644
--- a/app/uk/gov/hmrc/gform/testonly/TestOnlyController.scala
+++ b/app/uk/gov/hmrc/gform/testonly/TestOnlyController.scala
@@ -1035,7 +1035,7 @@ class TestOnlyController(
           _ <- if (useOriginalTemplate) {
                  ().pure[Future]
                } else gformConnector.restoreSnapshotTemplate(snapshotId.value)
-          _ <- newFormController.continue(cache, formTemplateContext.formTemplate)
+          _ <- newFormController.continue(cache, formTemplateContext.formTemplate, SuppressErrors.Yes)
         } yield Redirect(
           uk.gov.hmrc.gform.testonly.routes.TestOnlyController.restoreContinue(
             formTemplateId,
diff --git a/app/uk/gov/hmrc/gform/views/hardcoded/AccessCodeEnter.scala b/app/uk/gov/hmrc/gform/views/hardcoded/AccessCodeEnter.scala
index d666b89e9a..f42168dc7b 100644
--- a/app/uk/gov/hmrc/gform/views/hardcoded/AccessCodeEnter.scala
+++ b/app/uk/gov/hmrc/gform/views/hardcoded/AccessCodeEnter.scala
@@ -16,18 +16,24 @@
 
 package uk.gov.hmrc.gform.views.hardcoded
 
+import cats.implicits.catsSyntaxEq
 import play.api.data.{ Form, FormError }
 import play.api.i18n.Messages
 import play.twirl.api.{ Html, HtmlFormat }
 import uk.gov.hmrc.gform.gform.AccessCodeForm
 import uk.gov.hmrc.gform.models.AccessCodePage
-import uk.gov.hmrc.gform.sharedmodel.formtemplate.FormTemplate
+import uk.gov.hmrc.gform.sharedmodel.formtemplate.{ FormTemplate, SuppressErrors }
 import uk.gov.hmrc.govukfrontend.views.html.components._
 import uk.gov.hmrc.govukfrontend.views.html.helpers.{ GovukFormGroup, GovukHintAndErrorMessage }
 import uk.gov.hmrc.govukfrontend.views.viewmodels.errormessage.ErrorMessage
 import uk.gov.hmrc.govukfrontend.views.viewmodels.errorsummary.{ ErrorLink, ErrorSummary }
 
-class AccessCodeEnter(val formTemplate: FormTemplate, form: Form[AccessCodeForm], val isContinue: Boolean)(implicit
+class AccessCodeEnter(
+  val formTemplate: FormTemplate,
+  form: Form[AccessCodeForm],
+  val isContinue: Boolean,
+  se: SuppressErrors
+)(implicit
   messages: Messages
 ) extends CommonPageProperties(formTemplate) {
 
@@ -44,12 +50,14 @@ class AccessCodeEnter(val formTemplate: FormTemplate, form: Form[AccessCodeForm]
 
   val errorSummary: ErrorSummary = {
 
-    val errorsHtml: Seq[ErrorLink] = (form.errors ++ form.globalErrors).map { error =>
-      ErrorLink(
-        href = Some("#" + error.key),
-        content = Text(messages(s"${error.key}.${error.message}", formCategory))
-      )
-    }
+    val errorsHtml: Seq[ErrorLink] = (form.errors ++ form.globalErrors)
+      .filterNot(error => error.key.contains(AccessCodePage.isContinueKey))
+      .map { error =>
+        ErrorLink(
+          href = Some("#" + error.key),
+          content = Text(messages(s"${error.key}.${error.message}", formCategory))
+        )
+      }
 
     ErrorSummary(
       errorList = errorsHtml,
@@ -57,16 +65,22 @@ class AccessCodeEnter(val formTemplate: FormTemplate, form: Form[AccessCodeForm]
     )
   }
 
-  val hasErrors: Boolean = errorSummary.errorList.nonEmpty
+  val hasErrors: Boolean =
+    if (se === SuppressErrors.No)
+      errorSummary.errorList.nonEmpty
+    else false
 
   val render: Html = {
 
-    val errorMessage: Option[ErrorMessage] = form.errors.headOption.map { error =>
-      val message = messages(s"${error.key}.${error.message}", formCategory)
-      ErrorMessage.errorMessageWithDefaultStringsTranslated(
-        content = Text(message)
-      )
-    }
+    val errorMessage: Option[ErrorMessage] = form.errors
+      .filterNot(error => error.key.contains(AccessCodePage.isContinueKey))
+      .headOption
+      .map { error =>
+        val message = messages(s"${error.key}.${error.message}", formCategory)
+        ErrorMessage.errorMessageWithDefaultStringsTranslated(
+          content = Text(message)
+        )
+      }
 
     val accessCodeError: Option[FormError] = form.error(AccessCodePage.key)
 
@@ -89,7 +103,7 @@ class AccessCodeEnter(val formTemplate: FormTemplate, form: Form[AccessCodeForm]
         hint = Some(hint),
         value = Some(accessCodeValue),
         classes = "govuk-input--width-10",
-        errorMessage = accessCodeError.flatMap(_ => errorMessage)
+        errorMessage = if (hasErrors) accessCodeError.flatMap(_ => errorMessage) else None
       )
       val inputHtml = new GovukInput(govukLabel, govukFormGroup, govukHintAndErrorMessage)(input)
       HtmlFormat.fill(List(inputHtml))
diff --git a/app/uk/gov/hmrc/gform/views/hardcoded/AccessCodeStart.scala b/app/uk/gov/hmrc/gform/views/hardcoded/AccessCodeStart.scala
index afeb0c70b6..5e22bab4a2 100644
--- a/app/uk/gov/hmrc/gform/views/hardcoded/AccessCodeStart.scala
+++ b/app/uk/gov/hmrc/gform/views/hardcoded/AccessCodeStart.scala
@@ -16,19 +16,25 @@
 
 package uk.gov.hmrc.gform.views.hardcoded
 
+import cats.implicits.catsSyntaxEq
 import play.api.data.{ Form, FormError }
 import play.api.i18n.Messages
 import play.twirl.api.Html
 import uk.gov.hmrc.gform.config.FrontendAppConfig
 import uk.gov.hmrc.gform.models.AccessCodePage
-import uk.gov.hmrc.gform.sharedmodel.formtemplate.FormTemplate
+import uk.gov.hmrc.gform.sharedmodel.formtemplate.{ FormTemplate, SuppressErrors }
 import uk.gov.hmrc.govukfrontend.views.html.components._
 import uk.gov.hmrc.govukfrontend.views.html.helpers.{ GovukFormGroup, GovukHintAndErrorMessage }
 import uk.gov.hmrc.govukfrontend.views.viewmodels.errormessage.ErrorMessage
 import uk.gov.hmrc.govukfrontend.views.viewmodels.errorsummary.{ ErrorLink, ErrorSummary }
 import uk.gov.hmrc.govukfrontend.views.viewmodels.radios.{ RadioItem, Radios }
 
-class AccessCodeStart(val formTemplate: FormTemplate, form: Form[String], frontendAppConfig: FrontendAppConfig)(implicit
+class AccessCodeStart(
+  val formTemplate: FormTemplate,
+  form: Form[String],
+  frontendAppConfig: FrontendAppConfig,
+  se: SuppressErrors
+)(implicit
   messages: Messages
 ) extends CommonPageProperties(formTemplate) {
 
@@ -57,7 +63,10 @@ class AccessCodeStart(val formTemplate: FormTemplate, form: Form[String], fronte
     )
   }
 
-  val hasErrors: Boolean = errorSummary.errorList.nonEmpty
+  val hasErrors: Boolean =
+    if (se === SuppressErrors.No)
+      errorSummary.errorList.nonEmpty
+    else false
 
   val render: Html = {
 
@@ -109,7 +118,7 @@ class AccessCodeStart(val formTemplate: FormTemplate, form: Form[String], fronte
 
     val radios = Radios(
       fieldset = fieldset,
-      errorMessage = optionError.flatMap(_ => errorMessage),
+      errorMessage = if (hasErrors) optionError.flatMap(_ => errorMessage) else None,
       name = "accessOption",
       items = List(startNew, useExisting, divider, downloadSubmitted)
     )
diff --git a/app/uk/gov/hmrc/gform/views/hardcoded/pages/download_then_new.scala.html b/app/uk/gov/hmrc/gform/views/hardcoded/pages/download_then_new.scala.html
index 96eb9acc14..2eab21f76c 100644
--- a/app/uk/gov/hmrc/gform/views/hardcoded/pages/download_then_new.scala.html
+++ b/app/uk/gov/hmrc/gform/views/hardcoded/pages/download_then_new.scala.html
@@ -43,7 +43,7 @@
     formTemplate = downloadThenNewFormPage.formTemplate,
     frontendAppConfig = frontendAppConfig,
     containsErrors = downloadThenNewFormPage.hasErrors,
-    accessCode = None
+    accessCode = downloadThenNewFormPage.maybeAccessCode
 ) {
     @if(downloadThenNewFormPage.hasErrors) {
         @govukErrorSummary(downloadThenNewFormPage.errorSummary)
diff --git a/conf/app.routes b/conf/app.routes
index 4a39a3dd28..4bbe128af5 100644
--- a/conf/app.routes
+++ b/conf/app.routes
@@ -12,7 +12,7 @@ POST          /email-auth/email-confirmed-continue
 GET           /composite-auth/auth-selection-form/:formTemplateId                                                uk.gov.hmrc.gform.gform.CompositeAuthController.authSelectionForm(formTemplateId: FormTemplateId, ggId: Option[String], continue: String, se: SuppressErrors ?= SuppressErrors.Yes)
 POST          /composite-auth/selected-form/:formTemplateId                                                      uk.gov.hmrc.gform.gform.CompositeAuthController.selectedForm(formTemplateId: FormTemplateId, ggId: Option[String], continue: String)
 
-GET           /new-form/:formTemplateId                                                                          uk.gov.hmrc.gform.gform.NewFormController.dashboard(formTemplateId: FormTemplateId)
+GET           /new-form/:formTemplateId                                                                          uk.gov.hmrc.gform.gform.NewFormController.dashboard(formTemplateId: FormTemplateId, se: SuppressErrors ?= SuppressErrors.Yes)
 GET           /new-form/:formTemplateId/clean                                                                    uk.gov.hmrc.gform.gform.NewFormController.dashboardClean(formTemplateId: FormTemplateId)
 GET           /new-form/:formTemplateId/new-form-link                                                            uk.gov.hmrc.gform.gform.NewFormController.dashboardNewFormLink(formTemplateId: FormTemplateId)
 GET           /new-form/:formTemplateId/session                                                                  uk.gov.hmrc.gform.gform.NewFormController.dashboardWithNewSession(formTemplateId: FormTemplateId)
@@ -20,8 +20,8 @@ GET           /new-form/:formTemplateId/composite
 GET           /new-form/:formTemplateId/show-access-code                                                         uk.gov.hmrc.gform.gform.NewFormController.showAccessCode(formTemplateId: FormTemplateId)
 POST          /new-form/:formTemplateId/submission-reference                                                     uk.gov.hmrc.gform.gform.NewFormController.newSubmissionReference(formTemplateId: FormTemplateId)
 POST          /new-form/:formTemplateId                                                                          uk.gov.hmrc.gform.gform.NewFormController.newFormPost(formTemplateId: FormTemplateId)
-GET           /new-form/:formTemplateId/access-code-download                                                     uk.gov.hmrc.gform.gform.NewFormController.accessCodeDownload(formTemplateId: FormTemplateId)
-GET           /new-form/:formTemplateId/access-code-continue                                                     uk.gov.hmrc.gform.gform.NewFormController.accessCodeRetrieveForm(formTemplateId: FormTemplateId)
+GET           /new-form/:formTemplateId/access-code-download                                                     uk.gov.hmrc.gform.gform.NewFormController.accessCodeDownload(formTemplateId: FormTemplateId, se: SuppressErrors ?= SuppressErrors.Yes)
+GET           /new-form/:formTemplateId/access-code-continue                                                     uk.gov.hmrc.gform.gform.NewFormController.accessCodeRetrieveForm(formTemplateId: FormTemplateId, se: SuppressErrors ?= SuppressErrors.Yes)
 POST          /new-form/:formTemplateId/access-check                                                             uk.gov.hmrc.gform.gform.NewFormController.accessCodePost(formTemplateId: FormTemplateId)
 GET           /new-form/:formTemplateId/one-per-user                                                             uk.gov.hmrc.gform.gform.NewFormController.newOrContinue(formTemplateId: FormTemplateId)
 GET           /new-form/:formTemplateId/new-or-previous                                                          uk.gov.hmrc.gform.gform.NewFormController.downloadOldOrNewForm(formTemplateId: FormTemplateId, se: SuppressErrors ?= SuppressErrors.Yes)


Reviews:
user: login: josef-vlach
body: I'm perplexed why this machinery is needed?

Isn't this issue just a matter of missing `GET` routes for corresponding `POST` ?
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-15T16:07:00Z
user: login: josef-vlach
body: This is not ideal because it leaks `csrfToken` into url. Which I guess would not be deemed accessible.

See other comment for suggestions and take
```
POST          /new-form/:formTemplateId/download-decision
```

as an inspiration of how to handle POST correctly.
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-15T16:26:56Z
user: login: josef-vlach
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-17T12:32:49Z
user: login: cmanson
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-17T13:34:06Z
user: login: josef-vlach
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-17T13:47:57Z
user: login: josef-vlach
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-17T16:21:13Z

Review comments:
diff_hunk: @@ -59,15 +58,36 @@ class LanguageSwitchController(
   ): Action[AnyContent] =
     actionBuilder.async(request =>
       auth
-        .isLoggedIn(request)
-        .flatMap(isLoggedIn =>
-          if (isLoggedIn) {
-            // Presence of formTemplateId in the request doesn't guarantee the user data form exists
-            // We need to be sure that call to authAndRetrieveForm will succeed for language switch to occur
-            switchLanguageWithDataChange(formTemplateId, maybeAccessCode, language)(request)
-          } else {
-            // We are not logged in, let's just switch the language
-            switchToLanguage(language)(request)
+        .getLoggedIn(request)
+        .flatMap(maybeAuthSuccessful =>
+          maybeAuthSuccessful.fold(switchToLanguage(language)(request)) { authSuccessful =>
+            for {
+              maybeFormTemplate <- gformConnector.maybeFormTemplate(formTemplateId)(hc(request), ec)
+              maybeDrm <-
+                maybeFormTemplate
+                  .map { formTemplate =>
+                    formTemplate.draftRetrieval
+                      .flatMap(dr => authSuccessful.retrievals.getAffinityGroup.flatMap(ag => dr.mapping.get(ag)))
+                      .collect {
+                        case BySubmissionReference                => BySubmissionReference
+                        case FormAccessCode(continueOrDeletePage) => FormAccessCodeForAgents(continueOrDeletePage)
+                      }
+                      .getOrElse((formTemplate.draftRetrievalMethod, authSuccessful.retrievals) match {
+                        case (BySubmissionReference, _)                    => BySubmissionReference
+                        case (drm @ FormAccessCodeForAgents(_), IsAgent()) => drm
+                        case (other, _)                                    => other
+                      })
+                  }
+                  .pure[Future]
+              res <- (maybeDrm, maybeAccessCode) match {
path: app/uk/gov/hmrc/gform/gform/LanguageSwitchController.scala
user: login: josef-vlach
body: This is suspicious. Why does this function (ie. `switchToLanguageDataChange`) has some special knowledge of `accessCode` (behind passing `accessCode` for auth purposes).

I can see that this solves issue on pages where there is `accessCode` used as a form field name. 

But what about other pages where this is not the case? On these pages welsh switching is not working as expected.

In my opinion we should keep this function as is and implement welsh switching in other way.
created_at: 2025-04-17T12:32:44Z
author_association: CONTRIBUTOR
diff_hunk: @@ -59,15 +58,36 @@ class LanguageSwitchController(
   ): Action[AnyContent] =
     actionBuilder.async(request =>
       auth
-        .isLoggedIn(request)
-        .flatMap(isLoggedIn =>
-          if (isLoggedIn) {
-            // Presence of formTemplateId in the request doesn't guarantee the user data form exists
-            // We need to be sure that call to authAndRetrieveForm will succeed for language switch to occur
-            switchLanguageWithDataChange(formTemplateId, maybeAccessCode, language)(request)
-          } else {
-            // We are not logged in, let's just switch the language
-            switchToLanguage(language)(request)
+        .getLoggedIn(request)
+        .flatMap(maybeAuthSuccessful =>
+          maybeAuthSuccessful.fold(switchToLanguage(language)(request)) { authSuccessful =>
+            for {
+              maybeFormTemplate <- gformConnector.maybeFormTemplate(formTemplateId)(hc(request), ec)
+              maybeDrm <-
+                maybeFormTemplate
+                  .map { formTemplate =>
+                    formTemplate.draftRetrieval
+                      .flatMap(dr => authSuccessful.retrievals.getAffinityGroup.flatMap(ag => dr.mapping.get(ag)))
+                      .collect {
+                        case BySubmissionReference                => BySubmissionReference
+                        case FormAccessCode(continueOrDeletePage) => FormAccessCodeForAgents(continueOrDeletePage)
+                      }
+                      .getOrElse((formTemplate.draftRetrievalMethod, authSuccessful.retrievals) match {
+                        case (BySubmissionReference, _)                    => BySubmissionReference
+                        case (drm @ FormAccessCodeForAgents(_), IsAgent()) => drm
+                        case (other, _)                                    => other
+                      })
+                  }
+                  .pure[Future]
+              res <- (maybeDrm, maybeAccessCode) match {
path: app/uk/gov/hmrc/gform/gform/LanguageSwitchController.scala
user: login: cmanson
body: So we've now got a couple of pages, where the user is logged in and the form requires an access code - but an access code isn't known yet. If we attempt to go through load cache with form before we know the access code, it redirects us to the dashboard. 

The old logic was:
* if not logged in - just switch lanugage
* if logged in - load form, data change and save, then switch language

The new logic now says
* if not logged in - just switch language
* if logged in...
 * if form requires access code and there isn't one - just switch language
 * otherwise go through standard load from, data change and save, then switch language

What scenario have I missed?
created_at: 2025-04-17T13:34:06Z
author_association: CONTRIBUTOR
diff_hunk: @@ -59,15 +58,36 @@ class LanguageSwitchController(
   ): Action[AnyContent] =
     actionBuilder.async(request =>
       auth
-        .isLoggedIn(request)
-        .flatMap(isLoggedIn =>
-          if (isLoggedIn) {
-            // Presence of formTemplateId in the request doesn't guarantee the user data form exists
-            // We need to be sure that call to authAndRetrieveForm will succeed for language switch to occur
-            switchLanguageWithDataChange(formTemplateId, maybeAccessCode, language)(request)
-          } else {
-            // We are not logged in, let's just switch the language
-            switchToLanguage(language)(request)
+        .getLoggedIn(request)
+        .flatMap(maybeAuthSuccessful =>
+          maybeAuthSuccessful.fold(switchToLanguage(language)(request)) { authSuccessful =>
+            for {
+              maybeFormTemplate <- gformConnector.maybeFormTemplate(formTemplateId)(hc(request), ec)
+              maybeDrm <-
+                maybeFormTemplate
+                  .map { formTemplate =>
+                    formTemplate.draftRetrieval
+                      .flatMap(dr => authSuccessful.retrievals.getAffinityGroup.flatMap(ag => dr.mapping.get(ag)))
+                      .collect {
+                        case BySubmissionReference                => BySubmissionReference
+                        case FormAccessCode(continueOrDeletePage) => FormAccessCodeForAgents(continueOrDeletePage)
+                      }
+                      .getOrElse((formTemplate.draftRetrievalMethod, authSuccessful.retrievals) match {
+                        case (BySubmissionReference, _)                    => BySubmissionReference
+                        case (drm @ FormAccessCodeForAgents(_), IsAgent()) => drm
+                        case (other, _)                                    => other
+                      })
+                  }
+                  .pure[Future]
+              res <- (maybeDrm, maybeAccessCode) match {
path: app/uk/gov/hmrc/gform/gform/LanguageSwitchController.scala
user: login: josef-vlach
body: Pages this PR is addressing should be using this endpoint:

```
/language/:lang
```

Rather then this one which is used when you are inside the journey itself.

```
/language/:formTemplateId/:maybeAccessCode/:lang
```

created_at: 2025-04-17T13:47:57Z
author_association: CONTRIBUTOR

PR comments:
user: login: platops-pr-bot
created_at: 2025-04-15T15:09:40Z
body: - `SBT` can be updated to `1.10.10` in [project/build.properties](https://github.com/hmrc/gform-frontend/blob/cm%2FGFORMS-3341/project/build.properties#L1)
- `Scala` can be updated from `2.13.12` to `2.13.16` in [build.sbt](https://github.com/hmrc/gform-frontend/blob/cm%2FGFORMS-3341/build.sbt#L13)
- `uk.gov.hmrc.sbt-distributables` can be updated to `2.6.0` in [project/plugins.sbt](https://github.com/hmrc/gform-frontend/blob/cm%2FGFORMS-3341/project/plugins.sbt#L11)
- `uk.gov.hmrc:bootstrap-frontend-play-30` can be updated to `8.6.0` in [project/Dependencies.scala](https://github.com/hmrc/gform-frontend/blob/cm%2FGFORMS-3341/project/Dependencies.scala#L1).
- `uk.gov.hmrc:emailaddress` can be updated to `3.8.0` in [project/Dependencies.scala](https://github.com/hmrc/gform-frontend/blob/cm%2FGFORMS-3341/project/Dependencies.scala#L1).
- `uk.gov.hmrc:play-frontend-hmrc-play-30` can be updated to `11.13.0` in [project/Dependencies.scala](https://github.com/hmrc/gform-frontend/blob/cm%2FGFORMS-3341/project/Dependencies.scala#L1).
- `uk.gov.hmrc:bootstrap-test-play-30` can be updated to `8.6.0` in [project/Dependencies.scala](https://github.com/hmrc/gform-frontend/blob/cm%2FGFORMS-3341/project/Dependencies.scala#L1).
- There is a bobby warning (builds will be prevented after 30 Sep 2025) - see the pr builder for details
author_association: NONE
user: login: josef-vlach
created_at: 2025-04-15T16:15:31Z
body: To elaborate on this. The issue is that `POST` request (below) is returning the html directly rather than via redirect.

```
POST          /new-form/:formTemplateId/access-check

author_association: CONTRIBUTOR
user: login: platops-pr-bot
created_at: 2025-04-17T10:15:48Z
body: - ~~`SBT` can be updated to `1.10.10` in [project/build.properties](https://github.com/hmrc/gform-frontend/blob/cm%2FGFORMS-3341/project/build.properties#L1)~~
- ~~`Scala` can be updated from `2.13.12` to `2.13.16` in [build.sbt](https://github.com/hmrc/gform-frontend/blob/cm%2FGFORMS-3341/build.sbt#L13)~~
- ~~`uk.gov.hmrc.sbt-distributables` can be updated to `2.6.0` in [project/plugins.sbt](https://github.com/hmrc/gform-frontend/blob/cm%2FGFORMS-3341/project/plugins.sbt#L11)~~
- ~~`uk.gov.hmrc:bootstrap-frontend-play-30` can be updated to `8.6.0` in [project/Dependencies.scala](https://github.com/hmrc/gform-frontend/blob/cm%2FGFORMS-3341/project/Dependencies.scala#L1).~~
- ~~`uk.gov.hmrc:emailaddress` can be updated to `3.8.0` in [project/Dependencies.scala](https://github.com/hmrc/gform-frontend/blob/cm%2FGFORMS-3341/project/Dependencies.scala#L1).~~
- ~~`uk.gov.hmrc:play-frontend-hmrc-play-30` can be updated to `11.13.0` in [project/Dependencies.scala](https://github.com/hmrc/gform-frontend/blob/cm%2FGFORMS-3341/project/Dependencies.scala#L1).~~
- ~~`uk.gov.hmrc:bootstrap-test-play-30` can be updated to `8.6.0` in [project/Dependencies.scala](https://github.com/hmrc/gform-frontend/blob/cm%2FGFORMS-3341/project/Dependencies.scala#L1).~~
- There is a bobby warning (builds will be prevented after 30 Sep 2025) - see the pr builder for details
author_association: NONE