Skip to content

Commit ffe92c9

Browse files
authored
DTR-820: PP1 Variation for a Suspended Budget Payment Plan (#158)
1 parent 9f694e4 commit ffe92c9

12 files changed

+1094
-359
lines changed

app/controllers/DirectDebitSummaryController.scala

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@ package controllers
1818

1919
import controllers.actions.*
2020
import models.UserAnswers
21+
import pages.{AmendPaymentAmountPage, AmendPlanEndDatePage, AmendPlanStartDatePage, ManagePaymentPlanTypePage, SuspensionPeriodRangeDatePage}
2122
import play.api.i18n.{I18nSupport, MessagesApi}
2223
import play.api.mvc.{Action, AnyContent, MessagesControllerComponents}
2324
import services.NationalDirectDebitService
24-
import queries.{DirectDebitReferenceQuery, PaymentPlanReferenceQuery, PaymentPlansCountQuery}
25+
import queries.{DirectDebitReferenceQuery, PaymentPlanDetailsQuery, PaymentPlanReferenceQuery, PaymentPlansCountQuery}
2526
import repositories.SessionRepository
2627
import uk.gov.hmrc.play.bootstrap.frontend.controller.FrontendBaseController
2728
import views.html.DirectDebitSummaryView
@@ -45,10 +46,10 @@ class DirectDebitSummaryController @Inject() (
4546
val userAnswers = request.userAnswers.getOrElse(UserAnswers(request.userId))
4647
userAnswers.get(DirectDebitReferenceQuery) match {
4748
case Some(reference) =>
48-
cleansePaymentReference(userAnswers).flatMap { _ =>
49+
cleanseUserData(userAnswers).flatMap { cleansedUserAnswers =>
4950
nddService.retrieveDirectDebitPaymentPlans(reference).flatMap { ddPaymentPlans =>
5051
for {
51-
updatedAnswers <- Future.fromTry(userAnswers.set(PaymentPlansCountQuery, ddPaymentPlans.paymentPlanCount))
52+
updatedAnswers <- Future.fromTry(cleansedUserAnswers.set(PaymentPlansCountQuery, ddPaymentPlans.paymentPlanCount))
5253
updatedAnswers <- Future.fromTry(updatedAnswers.set(DirectDebitReferenceQuery, reference))
5354
_ <- sessionRepository.set(updatedAnswers)
5455
} yield {
@@ -74,9 +75,15 @@ class DirectDebitSummaryController @Inject() (
7475
} yield Redirect(routes.DirectDebitSummaryController.onPageLoad())
7576
}
7677

77-
private def cleansePaymentReference(userAnswers: UserAnswers): Future[UserAnswers] =
78+
private def cleanseUserData(userAnswers: UserAnswers): Future[UserAnswers] =
7879
for {
7980
updatedUserAnswers <- Future.fromTry(userAnswers.remove(PaymentPlanReferenceQuery))
81+
updatedUserAnswers <- Future.fromTry(updatedUserAnswers.remove(PaymentPlanDetailsQuery))
82+
updatedUserAnswers <- Future.fromTry(updatedUserAnswers.remove(ManagePaymentPlanTypePage))
83+
updatedUserAnswers <- Future.fromTry(updatedUserAnswers.remove(AmendPaymentAmountPage))
84+
updatedUserAnswers <- Future.fromTry(updatedUserAnswers.remove(AmendPlanStartDatePage))
85+
updatedUserAnswers <- Future.fromTry(updatedUserAnswers.remove(AmendPlanEndDatePage))
86+
updatedUserAnswers <- Future.fromTry(updatedUserAnswers.remove(SuspensionPeriodRangeDatePage))
8087
_ <- sessionRepository.set(updatedUserAnswers)
8188
} yield updatedUserAnswers
8289
}

app/controllers/PaymentPlanDetailsController.scala

Lines changed: 71 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ import utils.Constants
3232
import viewmodels.checkAnswers.*
3333
import views.html.PaymentPlanDetailsView
3434

35+
import java.time.LocalDate
36+
import java.time.format.DateTimeFormatter
3537
import javax.inject.Inject
3638
import scala.concurrent.duration.*
3739
import scala.concurrent.{Await, ExecutionContext, Future}
@@ -59,28 +61,52 @@ class PaymentPlanDetailsController @Inject() (
5961
updatedAnswers <- Future.fromTry(updatedAnswers.set(ManagePaymentPlanTypePage, planDetail.planType))
6062
updatedAnswers <- planDetail.scheduledPaymentAmount match {
6163
case Some(amount) => Future.fromTry(updatedAnswers.set(AmendPaymentAmountPage, amount))
62-
case None => Future.successful(updatedAnswers)
64+
case _ => Future.successful(updatedAnswers)
6365
}
6466
updatedAnswers <- (planDetail.suspensionStartDate, planDetail.suspensionEndDate) match {
6567
case (Some(startDate), Some(endDate)) =>
6668
Future.fromTry(updatedAnswers.set(SuspensionPeriodRangeDatePage, SuspensionPeriodRange(startDate, endDate)))
6769
case _ => Future.successful(updatedAnswers)
6870
}
69-
updatedAnswers <- planDetail.scheduledPaymentEndDate match {
70-
case Some(endDate) => Future.fromTry(updatedAnswers.set(AmendPlanEndDatePage, endDate))
71-
case None => Future.successful(updatedAnswers)
71+
updatedAnswers <- planDetail.scheduledPaymentStartDate match {
72+
case Some(paymentStartDate) => Future.fromTry(updatedAnswers.set(AmendPlanEndDatePage, paymentStartDate))
73+
case _ => Future.successful(updatedAnswers)
7274
}
7375
updatedAnswers <- planDetail.scheduledPaymentEndDate match {
74-
case Some(endDate) => Future.fromTry(updatedAnswers.set(AmendPlanEndDatePage, endDate))
75-
case None => Future.successful(updatedAnswers)
76+
case Some(paymentEndDate) => Future.fromTry(updatedAnswers.set(AmendPlanEndDatePage, paymentEndDate))
77+
case _ => Future.successful(updatedAnswers)
7678
}
77-
updatedAnswers <- cleanseCancelPaymentPlanPage(updatedAnswers)
78-
_ <- sessionRepository.set(updatedAnswers)
79+
updatedAnswers <- cleanseSessionPages(updatedAnswers)
80+
showAllActionsFlag <- calculateShowAction(nddService, planDetail)
81+
_ <- sessionRepository.set(updatedAnswers)
7982
} yield {
80-
val flag: Future[Boolean] = calculateShowAction(nddService, planDetail)
81-
val showActions = Await.result(flag, 5.seconds)
83+
val showAmendLink = isAmendLinkVisible(showAllActionsFlag, planDetail)
84+
val showCancelLink = isCancelLinkVisible(showAllActionsFlag, planDetail)
85+
val showSuspendLink = isSuspendLinkVisible(showAllActionsFlag, planDetail)
8286
val summaryRows: Seq[SummaryListRow] = buildSummaryRows(planDetail)
83-
Ok(view(planDetail.planType, paymentPlanReference, showActions, summaryRows))
87+
val isSuspensionActive = isSuspendPeriodActive(planDetail)
88+
89+
val formattedSuspensionStartDate = planDetail.suspensionStartDate
90+
.map(_.format(DateTimeFormatter.ofPattern(Constants.longDateTimeFormatPattern)))
91+
.getOrElse("")
92+
93+
val formattedSuspensionEndDate = planDetail.suspensionEndDate
94+
.map(_.format(DateTimeFormatter.ofPattern(Constants.longDateTimeFormatPattern)))
95+
.getOrElse("")
96+
97+
Ok(
98+
view(
99+
planDetail.planType,
100+
paymentPlanReference,
101+
showAmendLink,
102+
showCancelLink,
103+
showSuspendLink,
104+
isSuspensionActive,
105+
formattedSuspensionStartDate,
106+
formattedSuspensionEndDate,
107+
summaryRows
108+
)
109+
)
84110
}
85111
}
86112
case _ =>
@@ -117,10 +143,14 @@ class PaymentPlanDetailsController @Inject() (
117143
AmendPlanStartDateSummary.row(planDetail.planType, planDetail.scheduledPaymentStartDate, Constants.shortDateTimeFormatPattern),
118144
AmendPlanEndDateSummary.row(planDetail.scheduledPaymentEndDate, Constants.shortDateTimeFormatPattern),
119145
PaymentsFrequencySummary.row(planDetail.scheduledPaymentFrequency),
120-
AmendPaymentAmountSummary.row(planDetail.planType, planDetail.scheduledPaymentAmount),
121-
AmendSuspendDateSummary.row(planDetail.suspensionStartDate, true), // true for start
122-
AmendSuspendDateSummary.row(planDetail.suspensionEndDate, false) // false for end
123-
)
146+
AmendPaymentAmountSummary.row(planDetail.planType, planDetail.scheduledPaymentAmount)
147+
) ++
148+
(if (isSuspendPeriodActive(planDetail)) {
149+
Seq(SuspensionPeriodRangeDateSummary.row(planDetail.suspensionStartDate, planDetail.suspensionEndDate))
150+
} else {
151+
Seq.empty
152+
})
153+
124154
case _ => // For Variable and Tax repayment plan
125155
Seq(
126156
AmendPaymentPlanTypeSummary.row(planDetail.planType),
@@ -145,31 +175,48 @@ class PaymentPlanDetailsController @Inject() (
145175
case Some(startDate) => nddService.isTwoDaysPriorPaymentDate(startDate)
146176
case None => Future.successful(true)
147177
}
148-
case PaymentPlanType.BudgetPaymentPlan.toString =>
149-
planDetail.scheduledPaymentEndDate match {
150-
case Some(startDate) => nddService.isThreeDaysPriorPlanEndDate(startDate)
151-
case None => Future.successful(true)
152-
}
153-
case PaymentPlanType.VariablePaymentPlan.toString =>
178+
case PaymentPlanType.BudgetPaymentPlan.toString | PaymentPlanType.VariablePaymentPlan.toString =>
154179
for {
155180
isTwoDaysBeforeStart <- planDetail.scheduledPaymentStartDate match {
156181
case Some(startDate) => nddService.isTwoDaysPriorPaymentDate(startDate)
157-
case None => Future.successful(true)
182+
case _ => Future.successful(true)
158183
}
159184
isThreeDaysBeforeEnd <- planDetail.scheduledPaymentEndDate match {
160185
case Some(endDate) => nddService.isThreeDaysPriorPlanEndDate(endDate)
161-
case None => Future.successful(true)
186+
case _ => Future.successful(true)
162187
}
163188
} yield isTwoDaysBeforeStart && isThreeDaysBeforeEnd
164189

165190
case _ => Future.successful(false) // For TaxCredit repayment plan
166191
}
167192
}
168193

169-
private def cleanseCancelPaymentPlanPage(userAnswers: UserAnswers): Future[UserAnswers] =
194+
private def cleanseSessionPages(userAnswers: UserAnswers): Future[UserAnswers] =
170195
for {
171196
updatedUserAnswers <- Future.fromTry(userAnswers.remove(CancelPaymentPlanPage))
197+
updatedUserAnswers <- Future.fromTry(updatedUserAnswers.remove(DuplicateWarningPage))
172198
_ <- sessionRepository.set(updatedUserAnswers)
173199
} yield updatedUserAnswers
174200

201+
private def isAmendLinkVisible(showAllActionsFlag: Boolean, planDetail: PaymentPlanDetails): Boolean = {
202+
showAllActionsFlag && (planDetail.planType == PaymentPlanType.SinglePaymentPlan.toString || planDetail.planType == PaymentPlanType.BudgetPaymentPlan.toString)
203+
}
204+
205+
private def isCancelLinkVisible(showAllActionsFlag: Boolean, planDetail: PaymentPlanDetails): Boolean = {
206+
showAllActionsFlag && planDetail.planType != PaymentPlanType.TaxCreditRepaymentPlan.toString
207+
}
208+
209+
private def isSuspendLinkVisible(showAllActionsFlag: Boolean, planDetail: PaymentPlanDetails): Boolean = {
210+
planDetail.planType match {
211+
case planType if planType == PaymentPlanType.BudgetPaymentPlan.toString =>
212+
showAllActionsFlag && !isSuspendPeriodActive(planDetail)
213+
case _ => false
214+
}
215+
}
216+
217+
private def isSuspendPeriodActive(planDetail: PaymentPlanDetails): Boolean = {
218+
(for {
219+
suspensionEndDate <- planDetail.suspensionEndDate
220+
} yield !LocalDate.now().isAfter(suspensionEndDate)).getOrElse(false)
221+
}
175222
}

app/controllers/YourDirectDebitInstructionsController.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import controllers.actions.*
2121
import models.UserAnswers
2222
import play.api.i18n.{I18nSupport, MessagesApi}
2323
import play.api.mvc.{Action, AnyContent, MessagesControllerComponents}
24-
import queries.{DirectDebitReferenceQuery, PaymentPlanReferenceQuery}
24+
import queries.{DirectDebitReferenceQuery, PaymentPlansCountQuery}
2525
import repositories.SessionRepository
2626
import services.NationalDirectDebitService
2727
import uk.gov.hmrc.play.bootstrap.frontend.controller.FrontendBaseController
@@ -55,8 +55,8 @@ class YourDirectDebitInstructionsController @Inject() (
5555

5656
private def cleanseDirectDebitReference(userAnswers: UserAnswers): Future[UserAnswers] =
5757
for {
58-
userAnswersWithoutDirectDebitReference <- Future.fromTry(userAnswers.remove(DirectDebitReferenceQuery))
59-
userAnswersPaymentReference <- Future.fromTry(userAnswersWithoutDirectDebitReference.remove(PaymentPlanReferenceQuery))
60-
_ <- sessionRepository.set(userAnswersPaymentReference)
61-
} yield userAnswersPaymentReference
58+
updatedUserAnswers <- Future.fromTry(userAnswers.remove(DirectDebitReferenceQuery))
59+
updatedUserAnswers <- Future.fromTry(updatedUserAnswers.remove(PaymentPlansCountQuery))
60+
_ <- sessionRepository.set(updatedUserAnswers)
61+
} yield updatedUserAnswers
6262
}

app/viewmodels/checkAnswers/AmendSuspendDateSummary.scala

Lines changed: 0 additions & 44 deletions
This file was deleted.

app/viewmodels/checkAnswers/SuspensionPeriodRangeDateSummary.scala

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,18 @@
3333
package viewmodels.checkAnswers
3434

3535
import controllers.routes
36-
import models.{CheckMode, SuspensionPeriodRange, UserAnswers}
36+
import models.{CheckMode, NormalMode, SuspensionPeriodRange, UserAnswers}
3737
import pages.SuspensionPeriodRangeDatePage
3838
import play.api.i18n.{Lang, Messages}
3939
import uk.gov.hmrc.govukfrontend.views.viewmodels.summarylist.SummaryListRow
40+
import utils.Constants
4041
import utils.DateTimeFormats.formattedDateTimeShort
4142
import viewmodels.govuk.summarylist.*
4243
import viewmodels.implicits.*
4344

45+
import java.time.LocalDate
46+
import java.time.format.DateTimeFormatter
47+
4448
object SuspensionPeriodRangeDateSummary {
4549
def row(answers: UserAnswers, showChange: Boolean = false)(implicit messages: Messages): Option[SummaryListRow] =
4650
answers.get(SuspensionPeriodRangeDatePage).map { answer =>
@@ -62,4 +66,29 @@ object SuspensionPeriodRangeDateSummary {
6266
}
6367
)
6468
}
69+
70+
def row(suspendStartDate: Option[LocalDate], suspendEndDate: Option[LocalDate])(implicit messages: Messages): SummaryListRow = {
71+
val formattedStartDate = suspendStartDate
72+
.map(_.format(DateTimeFormatter.ofPattern(Constants.shortDateTimeFormatPattern)))
73+
.getOrElse("")
74+
75+
val formattedEndDate = suspendEndDate
76+
.map(_.format(DateTimeFormatter.ofPattern(Constants.shortDateTimeFormatPattern)))
77+
.getOrElse("")
78+
79+
val formattedValue =
80+
s"$formattedStartDate ${messages("suspensionPeriodRangeDate.to")} $formattedEndDate"
81+
82+
SummaryListRowViewModel(
83+
key = "suspensionPeriodRangeDate.checkYourAnswersLabel",
84+
value = ValueViewModel(formattedValue),
85+
actions = Seq(
86+
ActionItemViewModel("site.change", routes.SuspensionPeriodRangeDateController.onPageLoad(NormalMode).url)
87+
.withVisuallyHiddenText(messages("suspensionPeriodRangeDate.change.hidden")),
88+
ActionItemViewModel("site.remove", routes.JourneyRecoveryController.onPageLoad().url) // TODO Updated after RM1
89+
.withVisuallyHiddenText(messages("suspensionPeriodRangeDate.change.hidden"))
90+
)
91+
)
92+
}
93+
6594
}

app/views/PaymentPlanDetailsView.scala.html

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*@
1616

1717
@import models.responses.*
18+
@import java.time.LocalDate
1819
@import java.time.format.DateTimeFormatter
1920
@import views.html.components.*
2021
@import utils.MaskAndFormatUtils.*
@@ -29,14 +30,17 @@
2930
govukSummaryList: GovukSummaryList
3031
)
3132

32-
@(planType: String, paymentReference: String, showActions: Boolean, rows: Seq[SummaryListRow])(implicit request: Request[_], messages: Messages)
33+
@(planType: String, paymentReference: String, showAmendLink: Boolean, showCancelLink: Boolean, showSuspendLink: Boolean, isSuspensionActive: Boolean, suspensionStartDate: String, suspensionEndDate: String, rows: Seq[SummaryListRow])(implicit request: Request[_], messages: Messages)
3334

3435
@layout(pageTitle = titleForManageJourneyNoForm(messages("paymentPlanDetails.title")), backLink = Some(routes.DirectDebitSummaryController.onPageLoad().url)) {
3536
@header1("paymentPlanDetails.heading")
3637
@paragraph("paymentPlanDetails.p1")
37-
@paragraph("paymentPlanDetails.p2")
38-
<p class="govuk-inset-text">@messages("paymentPlanDetails.inset.text")</p>
39-
@header2("paymentPlanDetails.heading")
38+
39+
@if(isSuspensionActive) {
40+
<p class="govuk-inset-text">
41+
@messages("paymentPlanDetails.inset.text", suspensionStartDate, suspensionEndDate)
42+
</p>
43+
}
4044

4145
@govukSummaryList(SummaryList(
4246
card = Some(Card(
@@ -46,17 +50,17 @@
4650
actions =
4751
Some(Actions(
4852
items = Seq(
49-
if (showActions && (planType == PaymentPlanType.SinglePaymentPlan.toString || planType == PaymentPlanType.BudgetPaymentPlan.toString)) ActionItem(
53+
if (showAmendLink) ActionItem(
5054
href = routes.AmendPaymentAmountController.onPageLoad(NormalMode).url,
5155
content = messages("paymentPlanDetails.details.amend"),
5256
visuallyHiddenText = Some(messages("Amend"))
5357
) else null,
54-
if (showActions && planType != PaymentPlanType.TaxCreditRepaymentPlan.toString) ActionItem(
58+
if (showCancelLink) ActionItem(
5559
href = routes.CancelPaymentPlanController.onPageLoad().url,
5660
content = messages("paymentPlanDetails.details.cancel"),
5761
visuallyHiddenText = Some(messages("Cancel"))
5862
) else null,
59-
if (showActions && planType == PaymentPlanType.BudgetPaymentPlan.toString) ActionItem(
63+
if (showSuspendLink) ActionItem(
6064
href = routes.SuspendPaymentPlanController.onPageLoad().url,
6165
content = messages("paymentPlanDetails.details.suspend"),
6266
visuallyHiddenText = Some(messages("Suspend"))

conf/messages.en

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -404,9 +404,8 @@ directDebitPaymentSummary.addPaymentButton = Add payment plan
404404

405405
paymentPlanDetails.title = Your payment plan details
406406
paymentPlanDetails.heading = Your payment plan details
407-
paymentPlanDetails.p1 = You can amend the details of your payment plan, or cancel it if it is no longer required, by following either the ''Amend payment plan'' or ''Cancel payment plan'' links below.
408-
paymentPlanDetails.p2 = If you wish to suspend your payment plan please follow the ''Suspend payment plan'' link below.
409-
paymentPlanDetails.inset.text = Payments due within the next 3 working days will not be affected by any changes made.
407+
paymentPlanDetails.p1 = If a payment is due within the next 3 working days, you will not be able to make any changes.
408+
paymentPlanDetails.inset.text = This payment plan is suspended from {0} to {1}.
410409
paymentPlanDetails.details.paymentReference = Payment reference: {0}
411410
paymentPlanDetails.details.amend = Amend
412411
paymentPlanDetails.details.cancel = Cancel

0 commit comments

Comments
 (0)