Skip to content

Commit

Permalink
Merge pull request #616 from hmrc/CVSRP-4673
Browse files Browse the repository at this point in the history
[CVSRP-4673] Extend to September with tapered generosity for July (70%) and August/September (60%)
  • Loading branch information
LadonJackson authored Apr 29, 2021
2 parents 1422b39 + ce4581b commit f71c3af
Show file tree
Hide file tree
Showing 38 changed files with 989 additions and 876 deletions.
55 changes: 18 additions & 37 deletions app/controllers/ConfirmationController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import cats.data.Validated.{Invalid, Valid}
import config.{CalculatorVersionConfiguration, FrontendAppConfig}
import controllers.actions._
import handlers.{ConfirmationControllerRequestHandler, ErrorHandler}
import models.UserAnswers
import models.{FurloughGrantRate, UserAnswers}
import navigation.Navigator
import play.api.i18n.MessagesApi
import play.api.mvc.{Action, AnyContent, MessagesControllerComponents}
Expand All @@ -30,9 +30,8 @@ import utils.{PagerDutyHelper, YearMonthHelper}
import viewmodels.{ConfirmationDataResultWithoutNicAndPension, PhaseOneConfirmationDataResult, PhaseTwoConfirmationDataResult}
import views.html._

import java.time.Month._
import javax.inject.Inject
import scala.concurrent.{ExecutionContext, Future}
import scala.concurrent.ExecutionContext

class ConfirmationController @Inject()(
override val messagesApi: MessagesApi,
Expand All @@ -43,58 +42,40 @@ class ConfirmationController @Inject()(
employeeTypeService: EmployeeTypeService,
viewWithDetailedBreakdowns: ConfirmationViewWithDetailedBreakdowns,
phaseTwoView: PhaseTwoConfirmationView,
noNicAndPensionView: NoNicAndPensionConfirmationView,
septemberConfirmationView: SeptemberConfirmationView,
octoberConfirmationView: OctoberConfirmationView,
extensionView: JrsExtensionConfirmationView,
auditService: AuditService,
val navigator: Navigator)(implicit val errorHandler: ErrorHandler, ec: ExecutionContext, appConfig: FrontendAppConfig)
extends BaseController with ConfirmationControllerRequestHandler with CalculatorVersionConfiguration with YearMonthHelper {

//scalastyle:off
def onPageLoad: Action[AnyContent] = (identify andThen getData andThen requireData).async { implicit request =>
def onPageLoad: Action[AnyContent] = (identify andThen getData andThen requireData) { implicit request =>
/** Uncomment line to create integration test cases when going through journeys, either manually or via test packs.
* Set the number of cases to the amount of cases that will be executed. */
// printOutConfirmationTestCases(request.userAnswers, loadResultData(request.userAnswers), 6)
// printOutConfirmationTestCases(request.userAnswers, loadResultData(request.userAnswers), 6)

loadResultData(request.userAnswers) match {
case Valid(data: PhaseOneConfirmationDataResult) =>
auditService.sendCalculationPerformed(request.userAnswers, data.confirmationViewBreakdown)
Future.successful(Ok(viewWithDetailedBreakdowns(data.confirmationViewBreakdown, data.metaData.claimPeriod, calculatorVersionConf)))
Ok(viewWithDetailedBreakdowns(data.confirmationViewBreakdown, data.metaData.claimPeriod, calculatorVersionConf))
case Valid(data: PhaseTwoConfirmationDataResult) =>
auditService.sendCalculationPerformed(request.userAnswers, data.confirmationViewBreakdown)
Future.successful(Ok(phaseTwoView(data.confirmationViewBreakdown, data.metaData.claimPeriod, calculatorVersionConf)))
case Valid(data: ConfirmationDataResultWithoutNicAndPension) =>
data.metaData.claimPeriod.start.getYearMonth match {
case yearMonth if yearMonth == AUGUST.inYear(y2020) =>
auditService.sendCalculationPerformed(request.userAnswers, data.confirmationViewBreakdown)
Future.successful(Ok(noNicAndPensionView(data.confirmationViewBreakdown, data.metaData.claimPeriod, calculatorVersionConf)))
case yearMonth if yearMonth == SEPTEMBER.inYear(y2020) =>
auditService.sendCalculationPerformed(request.userAnswers, data.confirmationViewBreakdown)
Future.successful(
Ok(septemberConfirmationView(data.confirmationViewBreakdown, data.metaData.claimPeriod, calculatorVersionConf)))
case yearMonth if yearMonth == OCTOBER.inYear(y2020) =>
auditService.sendCalculationPerformed(request.userAnswers, data.confirmationViewBreakdown)
Future.successful(Ok(octoberConfirmationView(data.confirmationViewBreakdown, data.metaData.claimPeriod, calculatorVersionConf)))
case yearMonth if yearMonth.isBetweenInclusive(appConfig.extensionStartDate.getYearMonth, appConfig.schemeEndDate.getYearMonth) =>
auditService.sendCalculationPerformed(request.userAnswers, data.confirmationViewBreakdown)
Future.successful(
Ok(
extensionView(
data.confirmationViewBreakdown,
data.metaData.claimPeriod,
calculatorVersionConf,
employeeTypeService.isType5NewStarter()
))
)
case _ =>
Future.successful(Redirect(routes.ErrorController.somethingWentWrong()))
}
Ok(phaseTwoView(data.confirmationViewBreakdown, data.metaData.claimPeriod, calculatorVersionConf))
case Valid(data: ConfirmationDataResultWithoutNicAndPension) => {
auditService.sendCalculationPerformed(request.userAnswers, data.confirmationViewBreakdown)
Ok(
extensionView(
data.confirmationViewBreakdown,
data.metaData.claimPeriod,
calculatorVersionConf,
employeeTypeService.isType5NewStarter(),
FurloughGrantRate.rateForYearMonth(data.metaData.claimPeriod.start.getYearMonth)
))
}
case Invalid(e) =>
auditService.sendCalculationFailed(request.userAnswers)
PagerDutyHelper.alert(CALCULATION_FAILED)
UserAnswers.logErrors(e)(logger)
Future.successful(Redirect(routes.ErrorController.somethingWentWrong()))
Redirect(routes.ErrorController.somethingWentWrong())
}
}

Expand Down
6 changes: 2 additions & 4 deletions app/models/CalculationResult.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,8 @@ package models

case class FurloughCalculationResult(total: BigDecimal, periodBreakdowns: Seq[FurloughBreakdown])
case class PhaseTwoFurloughCalculationResult(total: BigDecimal, periodBreakdowns: Seq[PhaseTwoFurloughBreakdown]) {
def seventy = periodBreakdowns.map(_.seventy).sum
def sixty = periodBreakdowns.map(_.sixty).sum
def seventyDiff = total - seventy
def sixtyDiff = total - sixty
def atRate(furloughGrantRate: FurloughGrantRate): BigDecimal = periodBreakdowns.map(_.grantAmount(furloughGrantRate)).sum
def diffAtRate(furloughGrantRate: FurloughGrantRate): BigDecimal = total - atRate(furloughGrantRate)
}
case class NicCalculationResult(total: BigDecimal, periodBreakdowns: Seq[NicBreakdown])
case class PhaseTwoNicCalculationResult(total: BigDecimal, periodBreakdowns: Seq[PhaseTwoNicBreakdown])
Expand Down
41 changes: 41 additions & 0 deletions app/models/FurloughGrantRate.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright 2021 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 models

import java.time.YearMonth
import java.time.Month._

sealed trait FurloughGrantRate {
val value: Int
def asPercentage: BigDecimal = BigDecimal(value) / 100
}
case object SixtyPercent extends FurloughGrantRate { override val value: Int = 60 }
case object SeventyPercent extends FurloughGrantRate { override val value: Int = 70 }
case object EightyPercent extends FurloughGrantRate { override val value: Int = 80 }

object FurloughGrantRate {

val yearMonthMap = Map[YearMonth, FurloughGrantRate](
YearMonth.of(2020, SEPTEMBER) -> SeventyPercent,
YearMonth.of(2020, OCTOBER) -> SixtyPercent,
YearMonth.of(2021, JULY) -> SeventyPercent,
YearMonth.of(2021, AUGUST) -> SixtyPercent,
YearMonth.of(2021, SEPTEMBER) -> SixtyPercent
).withDefaultValue(EightyPercent)

def rateForYearMonth(yearMonth: YearMonth): FurloughGrantRate = yearMonthMap(yearMonth)
}
15 changes: 9 additions & 6 deletions app/models/PeriodBreakdown.scala
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,15 @@ sealed trait PhaseTwoPeriodBreakdown {

final case class PhaseTwoFurloughBreakdown(grant: Amount, paymentWithPeriod: PaymentWithPhaseTwoPeriod, furloughCap: FurloughCap)
extends PhaseTwoPeriodBreakdown {
def isCapped: Boolean = (paymentWithPeriod.referencePay.value * 0.8) > furloughCap.value
def calculatedFurlough: String = Amount(paymentWithPeriod.referencePay.value * 0.8).halfUp.value.formatted("%.2f")
def calculatedSeventy: String = Amount(paymentWithPeriod.referencePay.value * 0.7).halfUp.value.formatted("%.2f")
def calculatedSixty: String = Amount(paymentWithPeriod.referencePay.value * 0.6).halfUp.value.formatted("%.2f")
def seventy = Amount((grant.value / 80) * 70).halfUp.value
def sixty = Amount((grant.value / 80) * 60).halfUp.value
def isCapped: Boolean = (paymentWithPeriod.referencePay.value * 0.8) > furloughCap.value

def grantAmount(furloughGrantRate: FurloughGrantRate): BigDecimal = furloughGrantRate match {
case EightyPercent => grant.value
case rate => Amount((grant.value / 80) * rate.value).halfUp.value
}

def calculatedFurlough(furloughGrantRate: FurloughGrantRate): String =
Amount(paymentWithPeriod.referencePay.value * furloughGrantRate.asPercentage).halfUp.value.formatted("%.2f")
}

final case class PhaseTwoNicBreakdown(grant: Amount,
Expand Down
75 changes: 10 additions & 65 deletions app/viewmodels/ConfirmationViewBreakdown.scala
Original file line number Diff line number Diff line change
Expand Up @@ -114,23 +114,18 @@ case class PhaseTwoConfirmationViewBreakdown(furlough: PhaseTwoFurloughCalculati
)
}

def detailedBreakdownMessageKeys(
isNewStarterType5: Boolean)(implicit messages: Messages, dataRequest: DataRequest[_], appConfig: FrontendAppConfig): Seq[String] = {
def detailedBreakdownMessageKeys(implicit messages: Messages, dataRequest: DataRequest[_], appConfig: FrontendAppConfig): Seq[String] = {
val helper = new BeenOnStatutoryLeaveHelper()
furlough.periodBreakdowns.headOption
.map {
_.paymentWithPeriod match {
case _: RegularPaymentWithPhaseTwoPeriod =>
Seq(
messages("phaseTwoDetailedBreakdown.p1.regular")
)
case _: AveragePaymentWithPhaseTwoPeriod if isNewStarterType5 =>
Seq(
messages("phaseTwoReferencePayBreakdown.extension.p1")
messages("phaseTwoDetailedBreakdown.p1.regular", EightyPercent.value)
)
case _: AveragePaymentWithPhaseTwoPeriod =>
Seq(
messages("phaseTwoDetailedBreakdown.p1.average", helper.boundaryStart(), helper.boundaryEnd())
messages("phaseTwoDetailedBreakdown.p1.average", helper.boundaryStart(), helper.boundaryEnd(), EightyPercent.value)
)
case _: CylbPaymentWithPhaseTwoPeriod =>
Seq(
Expand Down Expand Up @@ -186,27 +181,29 @@ case class ConfirmationViewBreakdownWithoutNicAndPension(furlough: PhaseTwoFurlo
}

def detailedBreakdownMessageKeys(
furloughRate: FurloughGrantRate,
isNewStarterType5: Boolean)(implicit messages: Messages, dataRequest: DataRequest[_], appConfig: FrontendAppConfig): Seq[String] = {

val helper = new BeenOnStatutoryLeaveHelper()

furlough.periodBreakdowns.headOption
.map {
_.paymentWithPeriod match {
case _: RegularPaymentWithPhaseTwoPeriod =>
Seq(
messages("phaseTwoDetailedBreakdown.p1.regular")
messages("phaseTwoDetailedBreakdown.p1.regular", furloughRate.value)
)
case avg: AveragePaymentWithPhaseTwoPeriod if isNewStarterType5 =>
case _: AveragePaymentWithPhaseTwoPeriod if isNewStarterType5 =>
Seq(
messages("phaseTwoDetailedBreakdown.no.nic.p1.extension", helper.boundaryStart(), helper.boundaryEnd())
messages("phaseTwoDetailedBreakdown.no.nic.p1.extension", helper.boundaryStart(), helper.boundaryEnd(), furloughRate.value)
)
case _: AveragePaymentWithPhaseTwoPeriod =>
Seq(
messages("phaseTwoDetailedBreakdown.p1.average", helper.boundaryStart(), helper.boundaryEnd())
messages("phaseTwoDetailedBreakdown.p1.average", helper.boundaryStart(), helper.boundaryEnd(), furloughRate.value)
)
case _: CylbPaymentWithPhaseTwoPeriod =>
Seq(
messages("phaseTwoDetailedBreakdown.no.nic.pension.p1.cylb.1"),
messages("phaseTwoDetailedBreakdown.no.nic.pension.p1.cylb.1", furloughRate.value),
messages("phaseTwoDetailedBreakdown.no.nic.pension.p1.cylb.2"),
messages("phaseTwoDetailedBreakdown.no.nic.pension.p1.cylb.3", helper.boundaryEnd())
)
Expand All @@ -229,58 +226,6 @@ case class ConfirmationViewBreakdownWithoutNicAndPension(furlough: PhaseTwoFurlo
type5bEmployeeResult = Some(messages("phaseTwoDetailedBreakdown.statLeave", start, end))
)
} else None

def detailedBreakdownMessageKeysSept()(implicit messages: Messages,
dataRequest: DataRequest[_],
appConfig: FrontendAppConfig): Seq[String] = {
val helper = new BeenOnStatutoryLeaveHelper()
furlough.periodBreakdowns.headOption
.map {
_.paymentWithPeriod match {
case _: RegularPaymentWithPhaseTwoPeriod =>
Seq(
messages("phaseTwoDetailedBreakdown.september.p1.regular")
)
case _: AveragePaymentWithPhaseTwoPeriod =>
Seq(
messages("phaseTwoDetailedBreakdown.september.p1.average")
)
case _: CylbPaymentWithPhaseTwoPeriod =>
Seq(
messages("phaseTwoDetailedBreakdown.september.no.nic.pension.p1.cylb.1"),
messages("phaseTwoDetailedBreakdown.no.nic.pension.p1.cylb.2"),
messages("phaseTwoDetailedBreakdown.no.nic.pension.p1.cylb.3", helper.boundaryEnd())
)
}
}
.getOrElse(Seq())
}

def detailedBreakdownMessageKeysOct()(implicit messages: Messages,
dataRequest: DataRequest[_],
appConfig: FrontendAppConfig): Seq[String] = {
val helper = new BeenOnStatutoryLeaveHelper()
furlough.periodBreakdowns.headOption
.map {
_.paymentWithPeriod match {
case _: RegularPaymentWithPhaseTwoPeriod =>
Seq(
messages("phaseTwoDetailedBreakdown.october.p1.regular")
)
case _: AveragePaymentWithPhaseTwoPeriod =>
Seq(
messages("phaseTwoDetailedBreakdown.october.p1.average")
)
case _: CylbPaymentWithPhaseTwoPeriod =>
Seq(
messages("phaseTwoDetailedBreakdown.october.no.nic.pension.p1.cylb.1"),
messages("phaseTwoDetailedBreakdown.no.nic.pension.p1.cylb.2"),
messages("phaseTwoDetailedBreakdown.no.nic.pension.p1.cylb.3", helper.boundaryEnd())
)
}
}
.getOrElse(Seq())
}
}

sealed trait Metadata
Expand Down
Loading

0 comments on commit f71c3af

Please sign in to comment.