Skip to content

Commit

Permalink
Merge pull request #609 from hmrc/CVSRP-4765b-Matt
Browse files Browse the repository at this point in the history
[CVSRP-4765b-Matt] Updated the confirmation page to cater for Statutory Leave
  • Loading branch information
peckover authored Mar 30, 2021
2 parents 525d0f9 + cf591ef commit 62bcde1
Show file tree
Hide file tree
Showing 34 changed files with 1,250 additions and 184 deletions.
16 changes: 4 additions & 12 deletions app/controllers/ConfirmationController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,21 @@

package controllers

import java.time.LocalDate

import cats.data.{NonEmptyChain, Validated}
import cats.data.Validated.{Invalid, Valid}
import config.{CalculatorVersionConfiguration, FrontendAppConfig}
import controllers.actions._
import handlers.{ConfirmationControllerRequestHandler, ErrorHandler}
import javax.inject.Inject
import models.EmployeeRTISubmission._
import models.{AnswerValidation, EmployeeRTISubmission, Period, UserAnswers}
import models.UserAnswers.AnswerV
import models.requests.DataRequest
import models.UserAnswers
import navigation.Navigator
import pages.{EmployeeRTISubmissionPage, EmployeeStartDatePage, PreviousFurloughPeriodsPage}
import play.api.i18n.MessagesApi
import play.api.mvc.{Action, AnyContent, MessagesControllerComponents, Result}
import play.api.mvc.{Action, AnyContent, MessagesControllerComponents}
import services.{AuditService, EmployeeTypeService}
import utils.ConfirmationTestCasesUtil.printOutConfirmationTestCases
import utils.PagerDutyHelper
import utils.PagerDutyHelper.PagerDutyKeys._
import viewmodels.{ConfirmationDataResult, ConfirmationDataResultWithoutNicAndPension, ConfirmationViewBreakdownWithoutNicAndPension, PhaseOneConfirmationDataResult, PhaseTwoConfirmationDataResult, ViewBreakdown}
import viewmodels.{ConfirmationDataResultWithoutNicAndPension, PhaseOneConfirmationDataResult, PhaseTwoConfirmationDataResult}
import views.html._

import javax.inject.Inject
import scala.concurrent.{ExecutionContext, Future}

class ConfirmationController @Inject()(
Expand Down
28 changes: 17 additions & 11 deletions app/models/Payment.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@
package models

import java.time.LocalDate

import play.api.libs.json.{Format, Json}
import services.PeriodHelper
import services.{AveragePayCalculator, PeriodHelper}
import services.Calculators._

case class PaymentDate(value: LocalDate)
Expand Down Expand Up @@ -158,10 +157,12 @@ sealed trait PaymentWithPhaseTwoPeriod {

def periodDays: Int = phaseTwoPeriod.periodWithPaymentDate.period.period.countDays

def furloughDays: Int = phaseTwoPeriod.periodWithPaymentDate.period match {
case fp: FullPeriod => fp.period.countDays
case pp: PartialPeriod => pp.partial.countDays
def furloughPeriod: Period = phaseTwoPeriod.periodWithPaymentDate.period match {
case fp: FullPeriod => fp.period
case pp: PartialPeriod => pp.partial
}

def furloughDays: Int = furloughPeriod.countDays
}

case class RegularPaymentWithPhaseTwoPeriod(regularPay: Amount, referencePay: Amount, phaseTwoPeriod: PhaseTwoPeriod)
Expand All @@ -173,12 +174,17 @@ case class RegularPaymentWithPhaseTwoPeriod(regularPay: Amount, referencePay: Am
case class AveragePaymentWithPhaseTwoPeriod(referencePay: Amount,
annualPay: Amount,
priorFurloughPeriod: Period,
phaseTwoPeriod: PhaseTwoPeriod)
extends PaymentWithPhaseTwoPeriod {
def basedOnDays: String = {
val daily = Amount(annualPay.value / priorFurloughPeriod.countDays).halfUp
(daily.value * furloughDays).formatted("%.2f")
}
phaseTwoPeriod: PhaseTwoPeriod,
statutoryLeaveData: Option[StatutoryLeaveData])
extends PaymentWithPhaseTwoPeriod with AveragePayCalculator {

def payMinusStatLeavePay: BigDecimal = annualPay.value - statutoryLeaveData.map(_.pay).getOrElse(0)

def priorPeriodFurloughMinusStatLeaveDays: Int = priorFurloughPeriod.countDays - statutoryLeaveData.map(_.days).getOrElse(0)

def basedOnDays: String =
daily(furloughPeriod, priorFurloughPeriod, annualPay, statutoryLeaveData).value.formatted("%.2f")

def basedOnHours: String = referencePay.value.formatted("%.2f")
}

Expand Down
13 changes: 13 additions & 0 deletions app/pages/HasEmployeeBeenOnStatutoryLeavePage.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,24 @@

package pages

import models.UserAnswers
import play.api.libs.json.JsPath

import scala.util.{Success, Try}

case object HasEmployeeBeenOnStatutoryLeavePage extends QuestionPage[Boolean] {

override def path: JsPath = JsPath \ toString

override def toString: String = "hasEmployeeBeenOnStatutoryLeave"

override def cleanup(value: Option[Boolean], userAnswers: UserAnswers): Try[UserAnswers] =
if (value.contains(false)) {
for {
updateOne <- userAnswers.remove(NumberOfStatLeaveDaysPage)
updateTwo <- updateOne.remove(StatutoryLeavePayPage)
} yield updateTwo
} else {
Success(userAnswers)
}
}
10 changes: 5 additions & 5 deletions app/services/AveragePayCalculator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -61,16 +61,16 @@ trait AveragePayCalculator extends Calculators {
basedOnDays
}

AveragePaymentWithPhaseTwoPeriod(referencePay, annualPay, priorFurloughPeriod, phaseTwoPeriod)
AveragePaymentWithPhaseTwoPeriod(referencePay, annualPay, priorFurloughPeriod, phaseTwoPeriod, statutoryLeaveData)
}

protected def averageDailyCalculator(period: Period, amount: Amount, statLeaveAmount: BigDecimal, statLeaveDays: Int): Amount =
Amount((amount.value - statLeaveAmount) / (period.countDays - statLeaveDays)).halfUp

private def daily(period: Period,
priorFurloughPeriod: Period,
annualPay: Amount,
statutoryLeaveData: Option[StatutoryLeaveData]): Amount = {
protected def daily(period: Period,
priorFurloughPeriod: Period,
annualPay: Amount,
statutoryLeaveData: Option[StatutoryLeaveData]): Amount = {

val statLeaveAmount: BigDecimal = statutoryLeaveData.fold[BigDecimal](0)(_.pay)
val statLeaveDays: Int = statutoryLeaveData.fold[Int](0)(_.days)
Expand Down
35 changes: 18 additions & 17 deletions app/utils/EmployeeTypeUtil.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ import utils.PagerDutyHelper.PagerDutyKeys.EMPLOYEE_TYPE_COULD_NOT_BE_RESOLVED
trait EmployeeTypeUtil extends FeatureSwitching with DataExtractor {

def regularPayResolver[T](
type1EmployeeResult: Option[T] = None,
type2aEmployeeResult: Option[T] = None,
type2bEmployeeResult: Option[T] = None)(implicit request: DataRequest[_], appConfig: FrontendAppConfig): Option[T] =
type1EmployeeResult: => Option[T] = None,
type2aEmployeeResult: => Option[T] = None,
type2bEmployeeResult: => Option[T] = None)(implicit request: DataRequest[_], appConfig: FrontendAppConfig): Option[T] =
(request.userAnswers.getV(RegularLengthEmployedPage), request.userAnswers.getV(ClaimPeriodStartPage)) match {
case (Valid(RegularLengthEmployed.Yes), _) =>
logger.debug("[EmployeeTypeUtil][regularPayResolver] Type 1 Employee")
Expand Down Expand Up @@ -69,10 +69,10 @@ trait EmployeeTypeUtil extends FeatureSwitching with DataExtractor {
}

def variablePayResolver[T](
type3EmployeeResult: Option[T] = None,
type4EmployeeResult: Option[T] = None,
type5aEmployeeResult: Option[T] = None,
type5bEmployeeResult: Option[T] = None)(implicit request: DataRequest[_], appConfig: FrontendAppConfig): Option[T] =
type3EmployeeResult: => Option[T] = None,
type4EmployeeResult: => Option[T] = None,
type5aEmployeeResult: => Option[T] = None,
type5bEmployeeResult: => Option[T] = None)(implicit request: DataRequest[_], appConfig: FrontendAppConfig): Option[T] =
request.userAnswers.getV(EmployeeStartedPage) match {
case Valid(EmployeeStarted.OnOrBefore1Feb2019) =>
logger.debug("[EmployeeTypeUtil][variablePayResolver] Type 3 Employee")
Expand Down Expand Up @@ -107,16 +107,17 @@ trait EmployeeTypeUtil extends FeatureSwitching with DataExtractor {
}

//noinspection ScalaStyle
def employeeTypeResolver[T](defaultResult: T,
regularPayEmployeeResult: Option[T] = None,
variablePayEmployeeResult: Option[T] = None,
type1EmployeeResult: Option[T] = None,
type2aEmployeeResult: Option[T] = None,
type2bEmployeeResult: Option[T] = None,
type3EmployeeResult: Option[T] = None,
type4EmployeeResult: Option[T] = None,
type5aEmployeeResult: Option[T] = None,
type5bEmployeeResult: Option[T] = None)(implicit request: DataRequest[_], appConfig: FrontendAppConfig): T = {
def employeeTypeResolver[T](
defaultResult: => T,
regularPayEmployeeResult: => Option[T] = None,
variablePayEmployeeResult: => Option[T] = None,
type1EmployeeResult: => Option[T] = None,
type2aEmployeeResult: => Option[T] = None,
type2bEmployeeResult: => Option[T] = None,
type3EmployeeResult: => Option[T] = None,
type4EmployeeResult: => Option[T] = None,
type5aEmployeeResult: => Option[T] = None,
type5bEmployeeResult: => Option[T] = None)(implicit request: DataRequest[_], appConfig: FrontendAppConfig): T = {
val defaultRegularResult: T = regularPayEmployeeResult.getOrElse(defaultResult)
val defaultVariableResult: T = variablePayEmployeeResult.getOrElse(defaultResult)
request.userAnswers.getV(PayMethodPage) match {
Expand Down
94 changes: 66 additions & 28 deletions app/viewmodels/ConfirmationViewBreakdown.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@

package viewmodels

import config.FrontendAppConfig
import models._
import java.time.LocalDate
import models.requests.DataRequest
import play.api.i18n.Messages
import services.{AuditBreakdown, AuditCalculationResult, AuditPeriodBreakdown}
import utils.EmployeeTypeUtil

sealed trait ConfirmationDataResult

Expand Down Expand Up @@ -111,31 +114,34 @@ case class PhaseTwoConfirmationViewBreakdown(furlough: PhaseTwoFurloughCalculati
)
}

def detailedBreakdownMessageKeys(isNewStarterType5: Boolean): Seq[String] =
def detailedBreakdownMessageKeys(
isNewStarterType5: Boolean)(implicit messages: Messages, dataRequest: DataRequest[_], appConfig: FrontendAppConfig): Seq[String] = {
val helper = new BeenOnStatutoryLeaveHelper()
furlough.periodBreakdowns.headOption
.map {
_.paymentWithPeriod match {
case _: RegularPaymentWithPhaseTwoPeriod =>
Seq(
"phaseTwoDetailedBreakdown.p1.regular"
messages("phaseTwoDetailedBreakdown.p1.regular")
)
case _: AveragePaymentWithPhaseTwoPeriod if isNewStarterType5 =>
Seq(
"phaseTwoReferencePayBreakdown.extension.p1"
messages("phaseTwoReferencePayBreakdown.extension.p1")
)
case _: AveragePaymentWithPhaseTwoPeriod =>
Seq(
"phaseTwoDetailedBreakdown.p1.average"
messages("phaseTwoDetailedBreakdown.p1.average", helper.boundaryStart(), helper.boundaryEnd())
)
case _: CylbPaymentWithPhaseTwoPeriod =>
Seq(
"phaseTwoDetailedBreakdown.p1.cylb.1",
"phaseTwoDetailedBreakdown.p1.cylb.2",
"phaseTwoDetailedBreakdown.p1.cylb.3"
messages("phaseTwoDetailedBreakdown.p1.cylb.1"),
messages("phaseTwoDetailedBreakdown.p1.cylb.2"),
messages("phaseTwoDetailedBreakdown.p1.cylb.3")
)
}
}
.getOrElse(Seq())
}

override def toAuditBreakdown: AuditBreakdown = {
val auditFurlough = AuditCalculationResult(
Expand All @@ -160,7 +166,8 @@ case class PhaseTwoConfirmationViewBreakdown(furlough: PhaseTwoFurloughCalculati
}
}

case class ConfirmationViewBreakdownWithoutNicAndPension(furlough: PhaseTwoFurloughCalculationResult) extends ViewBreakdown {
case class ConfirmationViewBreakdownWithoutNicAndPension(furlough: PhaseTwoFurloughCalculationResult)
extends ViewBreakdown with EmployeeTypeUtil {

val auditFurlough = AuditCalculationResult(
furlough.total,
Expand All @@ -178,71 +185,102 @@ case class ConfirmationViewBreakdownWithoutNicAndPension(furlough: PhaseTwoFurlo
)
}

def detailedBreakdownMessageKeys(isNewStarterType5: Boolean): Seq[String] =
def detailedBreakdownMessageKeys(
isNewStarterType5: Boolean)(implicit messages: Messages, dataRequest: DataRequest[_], appConfig: FrontendAppConfig): Seq[String] = {
val helper = new BeenOnStatutoryLeaveHelper()

furlough.periodBreakdowns.headOption
.map {
_.paymentWithPeriod match {
case _: RegularPaymentWithPhaseTwoPeriod =>
Seq(
"phaseTwoDetailedBreakdown.p1.regular"
messages("phaseTwoDetailedBreakdown.p1.regular")
)
case avg: AveragePaymentWithPhaseTwoPeriod if isNewStarterType5 =>
Seq("phaseTwoDetailedBreakdown.no.nic.p1.extension")
Seq(
messages("phaseTwoDetailedBreakdown.no.nic.p1.extension", helper.boundaryStart(), helper.boundaryEnd())
)
case _: AveragePaymentWithPhaseTwoPeriod =>
Seq("phaseTwoDetailedBreakdown.p1.average")
Seq(
messages("phaseTwoDetailedBreakdown.p1.average", helper.boundaryStart(), helper.boundaryEnd())
)
case _: CylbPaymentWithPhaseTwoPeriod =>
Seq(
"phaseTwoDetailedBreakdown.no.nic.pension.p1.cylb.1",
"phaseTwoDetailedBreakdown.no.nic.pension.p1.cylb.2",
"phaseTwoDetailedBreakdown.no.nic.pension.p1.cylb.3"
messages("phaseTwoDetailedBreakdown.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 statLeaveOnlyMessageKeys()(implicit messages: Messages, dataRequest: DataRequest[_], appConfig: FrontendAppConfig): Option[String] =
if (hasStatutoryLeaveData()) {

lazy val helper = new BeenOnStatutoryLeaveHelper()
lazy val start = helper.boundaryStart()
lazy val end = helper.boundaryEnd()

def detailedBreakdownMessageKeysSept: Seq[String] =
variablePayResolver(
type3EmployeeResult = Some(messages("phaseTwoDetailedBreakdown.statLeave.method2", start, end)),
type4EmployeeResult = Some(messages("phaseTwoDetailedBreakdown.statLeave", start, end)),
type5aEmployeeResult = Some(messages("phaseTwoDetailedBreakdown.statLeave", start, end)),
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(
"phaseTwoDetailedBreakdown.september.p1.regular"
messages("phaseTwoDetailedBreakdown.september.p1.regular")
)
case _: AveragePaymentWithPhaseTwoPeriod =>
Seq(
"phaseTwoDetailedBreakdown.september.p1.average"
messages("phaseTwoDetailedBreakdown.september.p1.average")
)
case _: CylbPaymentWithPhaseTwoPeriod =>
Seq(
"phaseTwoDetailedBreakdown.september.no.nic.pension.p1.cylb.1",
"phaseTwoDetailedBreakdown.no.nic.pension.p1.cylb.2",
"phaseTwoDetailedBreakdown.no.nic.pension.p1.cylb.3"
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: Seq[String] =
def detailedBreakdownMessageKeysOct()(implicit messages: Messages,
dataRequest: DataRequest[_],
appConfig: FrontendAppConfig): Seq[String] = {
val helper = new BeenOnStatutoryLeaveHelper()
furlough.periodBreakdowns.headOption
.map {
_.paymentWithPeriod match {
case _: RegularPaymentWithPhaseTwoPeriod =>
Seq(
"phaseTwoDetailedBreakdown.october.p1.regular"
messages("phaseTwoDetailedBreakdown.october.p1.regular")
)
case _: AveragePaymentWithPhaseTwoPeriod =>
Seq(
"phaseTwoDetailedBreakdown.october.p1.average"
messages("phaseTwoDetailedBreakdown.october.p1.average")
)
case _: CylbPaymentWithPhaseTwoPeriod =>
Seq(
"phaseTwoDetailedBreakdown.october.no.nic.pension.p1.cylb.1",
"phaseTwoDetailedBreakdown.no.nic.pension.p1.cylb.2",
"phaseTwoDetailedBreakdown.no.nic.pension.p1.cylb.3"
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 62bcde1

Please sign in to comment.