Skip to content

Commit 244f92c

Browse files
committed
DDCE-7698 Update declare the employee to exclude
1 parent 0f1ed35 commit 244f92c

File tree

9 files changed

+354
-35
lines changed

9 files changed

+354
-35
lines changed

app/controllers/ExclusionListController.scala

Lines changed: 96 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,16 @@ package controllers
1919
import config.PbikAppConfig
2020
import connectors.PbikConnector
2121
import controllers.actions.{AuthAction, NoSessionCheckAction}
22-
import models._
22+
import models.*
2323
import models.auth.AuthenticatedRequest
2424
import models.form.MandatoryRadioButton
2525
import models.v1.IabdType.IabdType
26-
import models.v1.exclusion._
26+
import models.v1.exclusion.*
2727
import models.v1.trace.{TracePeopleByNinoRequest, TracePeopleByPersonalDetailsRequest, TracePersonResponse}
2828
import play.api.Logging
2929
import play.api.data.Form
3030
import play.api.i18n.{I18nSupport, Messages, MessagesApi}
31-
import play.api.mvc._
31+
import play.api.mvc.*
3232
import services.{BikListService, ExclusionService, SessionService}
3333
import uk.gov.hmrc.domain.EmpRef
3434
import uk.gov.hmrc.http.HeaderCarrier
@@ -37,10 +37,11 @@ import uk.gov.hmrc.play.bootstrap.controller.WithUnsafeDefaultFormBinding
3737
import uk.gov.hmrc.play.bootstrap.frontend.controller.FrontendController
3838
import uk.gov.hmrc.play.http.HeaderCarrierConverter
3939
import utils.Exceptions.InvalidBikTypeException
40-
import utils._
40+
import utils.*
4141
import views.html.ErrorPage
42-
import views.html.exclusion._
42+
import views.html.exclusion.*
4343

44+
import java.lang.ProcessBuilder
4445
import javax.inject.{Inject, Singleton}
4546
import scala.concurrent.{ExecutionContext, Future}
4647

@@ -65,6 +66,8 @@ class ExclusionListController @Inject() (
6566
ninoExclusionSearchFormView: NinoExclusionSearchForm,
6667
noNinoExclusionSearchFormView: NoNinoExclusionSearchForm,
6768
searchResultsView: SearchResults,
69+
searchResultsMPBIKView: SearchResultsMPBIK,
70+
declareEmployeeMPBIKView: DeclareEmployeeMPBIK,
6871
whatNextExclusionView: WhatNextExclusion,
6972
removalConfirmationView: RemovalConfirmation,
7073
whatNextRescindView: WhatNextRescind
@@ -433,7 +436,8 @@ class ExclusionListController @Inject() (
433436
(authenticate andThen noSessionCheck).async { implicit request =>
434437
if (exclusionsAllowed) {
435438
val futureResult = formType match {
436-
case ControllersReferenceDataCodes.FORM_TYPE_NINO => searchResultsByNino(isCurrentTaxYear, iabdType, formType)
439+
case ControllersReferenceDataCodes.FORM_TYPE_NINO =>
440+
searchResultsByNino(isCurrentTaxYear, iabdType, formType)
437441
case ControllersReferenceDataCodes.FORM_TYPE_NONINO =>
438442
searchResultsByPersonalDetails(isCurrentTaxYear, iabdType, formType)
439443
}
@@ -511,17 +515,37 @@ class ExclusionListController @Inject() (
511515
)
512516
)
513517
}
514-
case _ =>
515-
Ok(
516-
searchResultsView(
517-
controllersReferenceData.yearRange,
518-
isCurrentTaxYear,
519-
iabdType,
520-
uniqueListOfMatches,
521-
formMappings.individualSelectionForm,
522-
formType
518+
case n =>
519+
if (mpbikToggle) {
520+
if (n == 1) { // testing with n < 1
521+
Redirect(
522+
routes.ExclusionListController
523+
.declareEmployeeToExclude(isCurrentTaxYear, iabdType)
524+
)
525+
} else {
526+
Ok(
527+
searchResultsMPBIKView(
528+
controllersReferenceData.yearRange,
529+
isCurrentTaxYear,
530+
iabdType,
531+
uniqueListOfMatches,
532+
formMappings.individualSelectionForm,
533+
formType
534+
)
535+
)
536+
}
537+
} else {
538+
Ok(
539+
searchResultsView(
540+
controllersReferenceData.yearRange,
541+
isCurrentTaxYear,
542+
iabdType,
543+
uniqueListOfMatches,
544+
formMappings.individualSelectionForm,
545+
formType
546+
)
523547
)
524-
)
548+
}
525549
}
526550
}
527551

@@ -533,29 +557,53 @@ class ExclusionListController @Inject() (
533557
.bindFromRequest()
534558
.fold(
535559
formWithErrors =>
536-
Future.successful(
537-
BadRequest(
538-
searchResultsView(
539-
controllersReferenceData.yearRange,
540-
year,
541-
iabdType,
542-
session.get.listOfMatches.get.pbikExclusionList,
543-
formWithErrors,
544-
formType
560+
if (mpbikToggle) {
561+
Future.successful(
562+
BadRequest(
563+
searchResultsMPBIKView(
564+
controllersReferenceData.yearRange,
565+
year,
566+
iabdType,
567+
session.get.listOfMatches.get.pbikExclusionList,
568+
formWithErrors,
569+
formType
570+
)
545571
)
546572
)
547-
),
573+
} else {
574+
Future.successful(
575+
BadRequest(
576+
searchResultsView(
577+
controllersReferenceData.yearRange,
578+
year,
579+
iabdType,
580+
session.get.listOfMatches.get.pbikExclusionList,
581+
formWithErrors,
582+
formType
583+
)
584+
)
585+
)
586+
},
548587
values => {
549588
val individualsDetails: Option[TracePersonResponse] =
550589
session.get.listOfMatches.get.pbikExclusionList
551590
.find(person => person.nationalInsuranceNumber == values.nino)
552-
validateRequest(year, iabdType).flatMap { _ =>
553-
commitExclusion(
554-
year,
555-
iabdType,
556-
session.get.listOfMatches.get.updatedEmployerOptimisticLock,
557-
individualsDetails
591+
if (mpbikToggle && individualsDetails.isDefined) {
592+
Future.successful(
593+
Redirect(
594+
routes.ExclusionListController
595+
.declareEmployeeToExclude(year, iabdType)
596+
)
558597
)
598+
} else {
599+
validateRequest(year, iabdType).flatMap { _ =>
600+
commitExclusion(
601+
year,
602+
iabdType,
603+
session.get.listOfMatches.get.updatedEmployerOptimisticLock,
604+
individualsDetails
605+
)
606+
}
559607
}
560608
}
561609
)
@@ -575,6 +623,22 @@ class ExclusionListController @Inject() (
575623
}
576624
}
577625

626+
def declareEmployeeToExclude(year: String, iabdType: IabdType): Action[AnyContent] =
627+
(authenticate andThen noSessionCheck).async { implicit request =>
628+
val resultFuture = for {
629+
_ <- validateRequest(year, iabdType)
630+
session <- sessionService.fetchPbikSession()
631+
} yield Ok(
632+
declareEmployeeMPBIKView(
633+
controllersReferenceData.yearRange,
634+
year,
635+
iabdType,
636+
session.get.listOfMatches.get.pbikExclusionList.head
637+
)
638+
)
639+
controllersReferenceData.responseErrorHandler(resultFuture)
640+
}
641+
578642
def commitExclusion(
579643
year: String,
580644
iabdType: IabdType,

app/utils/FormMappings.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ class FormMappings @Inject() (pbikAppConfig: PbikAppConfig, val messagesApi: Mes
170170
.verifying(
171171
Messages("error.incorrect.nino"),
172172
nino => cleanupNino(nino).isEmpty || cleanupNino(nino).matches(validNinoFormat)
173-
)
173+
)
174174
)((firstname, surname, nino) =>
175175
NinoForm(
176176
firstname.trim,
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
@*
2+
* Copyright 2026 HM Revenue & Customs
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*@
16+
17+
@import utils.TaxDateUtils
18+
@import views.templatemodels.PageTitle
19+
20+
@this(
21+
govukLayoutWrapper: GovukLayoutWrapper,
22+
govukWarningText: GovukWarningText,
23+
formWithCSRF: FormWithCSRF,
24+
taxDateUtils: TaxDateUtils
25+
)
26+
27+
@(
28+
taxYearRange: TaxYearRange,
29+
year: String,
30+
iabdType: IabdType,
31+
employee: TracePersonResponse
32+
)(implicit request: AuthenticatedRequest[?], messages: Messages)
33+
34+
@expenseOrBenefit = @{messages(s"BenefitInKind.label.${iabdType.id}")}
35+
@govukLayoutWrapper(PageTitle(messages("ExclusionSearchMPBIK.title.single"))) {
36+
37+
<h1 id="title" class="govuk-heading-xl">
38+
<span class="govuk-caption-l">@messages("ExclusionSearchMPBIK.title.span.taxYear.cy0", s"${taxYearRange.cy}", s"${taxYearRange.cyplus1}")</span>
39+
@messages("ExclusionSearchMPBIK.title.single")
40+
</h1>
41+
42+
<h2 class="govuk-heading-m">@expenseOrBenefit</h2>
43+
44+
<p class="govuk-body">@messages("ExclusionImportantMPBIK.Reminder", expenseOrBenefit, taxDateUtils.getDisplayTodayDate())</p>
45+
46+
<div class="govuk-inset-text">
47+
@messages("ExclusionSearchMPBIK.inset.text")
48+
</div>
49+
50+
<dl class="govuk-summary-list">
51+
<div class="govuk-summary-list__row">
52+
<dt class="govuk-summary-list__key">@messages("ExclusionSearchMPBIK.field.employee.name")</dt>
53+
<dd class="govuk-summary-list__value">@employee.fullName</dd>
54+
</div>
55+
<div class="govuk-summary-list__row">
56+
<dt class="govuk-summary-list__key">@messages("ExclusionSearchMPBIK.field.employee.ni")</dt>
57+
<dd class="govuk-summary-list__value">@employee.nationalInsuranceNumber</dd>
58+
</div>
59+
<div class="govuk-summary-list__row">
60+
<dt class="govuk-summary-list__key">@messages("ExclusionSearchMPBIK.field.employee.payrollId")</dt>
61+
<dd class="govuk-summary-list__value">@employee.getWorksPayrollNumber</dd>
62+
</div>
63+
</dl>
64+
65+
@govukWarningText(WarningText(
66+
iconFallbackText = Some(messages("site.warning")),
67+
content = Text(messages("ExclusionSearchMPBIK.warning"))
68+
))
69+
70+
<p id="i-confirm-that" class="govuk-body">
71+
@messages("ExclusionSearchMPBIK.confirmation." + request.userType + ".p")
72+
</p>
73+
<ul class="govuk-list govuk-list--bullet">
74+
<li>@messages("ExclusionSearchMPBIK.confirmation." + request.userType + ".bullet1")</li>
75+
<li>@messages("ExclusionSearchMPBIK.confirmation." + request.userType + ".bullet2")</li>
76+
</ul>
77+
78+
<p id="i-understand-that" class="govuk-body">
79+
@messages("ExclusionSearchMPBIK.understanding." + request.userType + ".p")
80+
</p>
81+
<ul class="govuk-list govuk-list--bullet">
82+
<li>@messages("ExclusionSearchMPBIK.understanding." + request.userType + ".bullet1")</li>
83+
</ul>
84+
85+
<div class="govuk-form-group">
86+
<a href="@routes.ExclusionListController.updateExclusions(year, iabdType)" class="govuk-button" role="button" id="button-confirm">@messages("Service.confirmAndContinue")</a>
87+
</div>
88+
89+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
@*
2+
* Copyright 2026 HM Revenue & Customs
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*@
16+
17+
@import utils.TaxDateUtils
18+
@import views.templatemodels.PageTitle
19+
20+
@this(
21+
govukLayoutWrapper: GovukLayoutWrapper,
22+
govukWarningText: GovukWarningText,
23+
formWithCSRF: FormWithCSRF,
24+
taxDateUtils: TaxDateUtils
25+
)
26+
27+
@(
28+
taxYearRange: TaxYearRange,
29+
year: String,
30+
iabdType: IabdType,
31+
listOfMatches: List[TracePersonResponse],
32+
listOfMatchesForm: Form[ExclusionNino],
33+
formType: String
34+
)(implicit request: Request[?], messages: Messages)
35+
36+
@govukLayoutWrapper(PageTitle(messages("ExclusionSearchMPBIK.title.multiple"), listOfMatchesForm.hasErrors)) {
37+
38+
@if(listOfMatchesForm("individualNino").hasErrors) {
39+
<div class="govuk-error-summary" role="group" aria-labelledby="error-summary-heading-1" tabindex="-1">
40+
41+
<h2 class="govuk-error-summary__title" id="error-summary-heading-1">
42+
@messages("Service.errorSummary.heading")
43+
</h2>
44+
<div class="govuk-error-summary__body">
45+
<ul class="govuk-list govuk-error-summary__list">
46+
@if(listOfMatchesForm.error("individualNino").get.message.equals("error.required")){
47+
<li><a href="#employee-radio-0">@messages("error.exclusion.multi.selection")</a></li>
48+
}
49+
</ul>
50+
</div>
51+
</div>
52+
}
53+
54+
<h1 id="title" class="govuk-heading-xl">
55+
<span class="govuk-caption-l">@messages("ExclusionSearchMPBIK.form.tax.year", s"${taxYearRange.cy}", s"${taxYearRange.cyplus1}")</span>
56+
@messages("ExclusionSearchMPBIK.title.multiple")
57+
</h1>
58+
59+
@formWithCSRF(action = routes.ExclusionListController.updateMultipleExclusions(year, iabdType, formType)) {
60+
<div class="govuk-form-group @if(listOfMatchesForm("individualNino").hasErrors){govuk-form-group--error}">
61+
<fieldset class="govuk-fieldset" @if(listOfMatchesForm("individualNino").hasErrors){aria-describedby="selection-error"}>
62+
@if(listOfMatchesForm("individualNino").hasErrors) {
63+
<span id="selection-error" class="govuk-error-message">
64+
<span class="govuk-visually-hidden">@messages("Service.error"):</span>
65+
@messages("error.exclusion.multi.selection")
66+
</span>
67+
}
68+
<div class="govuk-radios">
69+
@for(index <- 0 until listOfMatches.length) {
70+
<div class="govuk-radios__item">
71+
<input class="govuk-radios__input" id="employee-radio-@index" type="radio" aria-describedby="employee-hint-@index" name="individualNino" value='@listOfMatches(index).nationalInsuranceNumber'>
72+
<label class="govuk-label govuk-radios__label govuk-label--s" for="employee-radio-@index">
73+
@listOfMatches(index).fullName
74+
</label>
75+
<span id="employee-hint-@index" class="govuk-hint govuk-radios__hint">
76+
@messages("Service.field.nino"): @listOfMatches(index).nationalInsuranceNumber <br>
77+
@messages("Service.field.worksnumber"): @listOfMatches(index).getWorksPayrollNumber
78+
</span>
79+
</div>
80+
}
81+
</div>
82+
</fieldset>
83+
</div>
84+
85+
<input type="submit" class="govuk-button" role="button" id="button-continue" value="@messages("Service.continueMPBIK")">
86+
}
87+
}

conf/app.routes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ POST /:year/:iabdType/:formType/search-for-employee controllers.Exc
6363
GET /:year/:iabdType/:formType/exclude-employee-results controllers.ExclusionListController.showResults(year: String, iabdType: models.v1.IabdType.IabdType, formType: String)
6464
POST /:year/:iabdType/:formType/exclude-employee-results controllers.ExclusionListController.updateMultipleExclusions(year: String, iabdType: models.v1.IabdType.IabdType, formType: String)
6565
GET /:year/:iabdType/exclude-employee-results-single controllers.ExclusionListController.updateExclusions(year: String, iabdType: models.v1.IabdType.IabdType)
66+
GET /:year/:iabdType/declare-employee-exclusion controllers.ExclusionListController.declareEmployeeToExclude(year: String, iabdType: models.v1.IabdType.IabdType)
6667

6768
GET /:year/:iabdType/exclusion-complete controllers.ExclusionListController.showExclusionConfirmation(year: String, iabdType: models.v1.IabdType.IabdType)
6869

0 commit comments

Comments
 (0)