diff --git a/app/uk/gov/hmrc/tai/model/nps/NpsDate.scala b/app/uk/gov/hmrc/tai/model/nps/NpsDate.scala index 379dfaa1f..0bc519fde 100644 --- a/app/uk/gov/hmrc/tai/model/nps/NpsDate.scala +++ b/app/uk/gov/hmrc/tai/model/nps/NpsDate.scala @@ -20,7 +20,7 @@ import play.api.libs.json._ import uk.gov.hmrc.tai.model.nps.NpsDate._ import java.time.LocalDate -import java.time.format.DateTimeFormatter +import java.time.format.{DateTimeFormatter, DateTimeParseException} import scala.language.implicitConversions import scala.util.Try @@ -38,7 +38,7 @@ object NpsDate { } implicit val writes: Writes[NpsDate] = (date: NpsDate) => JsString(date.toNpsString) - private val taxPlatformDateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd") + private[nps] val taxPlatformDateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd") private val hipDateRegex = """^(\d\d\d\d)-(\d\d)-(\d\d)$""".r private val npsDateRegex = """^(\d\d)/(\d\d)/(\d\d\d\d)$""".r private val npsDateFormat = DateTimeFormatter.ofPattern("dd/MM/yyyy") @@ -59,19 +59,15 @@ object NpsDateImplicitConversions { implicit def localToNps(date: LocalDate): NpsDate = NpsDate(date) } -// TODO: Replace this with our existing date serialization code object localDateSerializer { - private val localDateRegex = """^(\d\d\d\d)-(\d\d)-(\d\d)$""".r + def deserialize(str: String): LocalDate = + try LocalDate.parse(str, NpsDate.taxPlatformDateFormat) + catch { + case _: DateTimeParseException => throw new IllegalArgumentException(parseError(str)) + } - def deserialize(str: String): LocalDate = str match { - case localDateRegex(y, m, d) => - LocalDate.of(y.toInt, m.toInt, d.toInt) - case _ => throw new Exception(parseError(str)) - } - - def serialize(value: LocalDate): String = - "%04d-%02d-%02d".format(value.getYear, value.getMonthValue, value.getDayOfMonth) + def serialize(value: LocalDate): String = value.format(NpsDate.taxPlatformDateFormat) private def parseError(str: String) = s"Unable to parse '$str' to type 'LocalDate', expected a valid value with format: yyyy-MM-dd" diff --git a/app/uk/gov/hmrc/tai/model/templates/PdfSubmission.scala b/app/uk/gov/hmrc/tai/model/templates/PdfSubmission.scala index 5555b59ef..3fc7ce8d6 100644 --- a/app/uk/gov/hmrc/tai/model/templates/PdfSubmission.scala +++ b/app/uk/gov/hmrc/tai/model/templates/PdfSubmission.scala @@ -27,7 +27,7 @@ case class PdfSubmission( formId: String, numberOfPages: Int, attachmentCount: Int = 0, - hmrcReceivedAt: LocalDateTime = LocalDateTime.now(ZoneId.of(LondonEuropeTimezone)), // TODO extract from config + hmrcReceivedAt: LocalDateTime = LocalDateTime.now(ZoneId.of(LondonEuropeTimezone)), submissionMark: String = "", casKey: String = "", businessArea: String = "PSA", @@ -48,3 +48,9 @@ case class PdfSubmission( val fileFormat = "pdf" val mimeType: String = "application/pdf" } + +object PdfSubmission { + + def apply(customerId: String, formId: String, numberOfPages: Int, timezone: String): PdfSubmission = + new PdfSubmission(customerId, formId, numberOfPages, hmrcReceivedAt = LocalDateTime.now(ZoneId.of(timezone))) +} diff --git a/app/uk/gov/hmrc/tai/service/CodingComponentService.scala b/app/uk/gov/hmrc/tai/service/CodingComponentService.scala index fb3b50baf..2f08a115f 100644 --- a/app/uk/gov/hmrc/tai/service/CodingComponentService.scala +++ b/app/uk/gov/hmrc/tai/service/CodingComponentService.scala @@ -17,6 +17,7 @@ package uk.gov.hmrc.tai.service import com.google.inject.{Inject, Singleton} +import play.api.libs.json.JsValue import uk.gov.hmrc.domain.Nino import uk.gov.hmrc.http.HeaderCarrier import uk.gov.hmrc.tai.connectors.TaxAccountConnector @@ -32,9 +33,10 @@ class CodingComponentService @Inject() ( )(implicit ec: ExecutionContext) { def codingComponents(nino: Nino, year: TaxYear)(implicit hc: HeaderCarrier): Future[Seq[CodingComponent]] = - taxAccountConnector - .taxAccount(nino, year) - .map(_.as[Seq[CodingComponent]](CodingComponentHipReads.codingComponentReads)) + codingComponents(taxAccountConnector.taxAccount(nino, year)) + + def codingComponents(taxAccountDetails: Future[JsValue]): Future[Seq[CodingComponent]] = + taxAccountDetails.map(_.as[Seq[CodingComponent]](CodingComponentHipReads.codingComponentReads)) def codingComponentsForTaxCodeId(nino: Nino, taxCodeId: Int)(implicit hc: HeaderCarrier diff --git a/app/uk/gov/hmrc/tai/service/IncomeService.scala b/app/uk/gov/hmrc/tai/service/IncomeService.scala index 2798e9c62..0bbb5ab49 100644 --- a/app/uk/gov/hmrc/tai/service/IncomeService.scala +++ b/app/uk/gov/hmrc/tai/service/IncomeService.scala @@ -20,6 +20,7 @@ import cats.data.EitherT import com.google.inject.{Inject, Singleton} import play.api.Logging import play.api.http.Status.NOT_FOUND +import play.api.libs.json.JsValue import play.api.mvc.Request import uk.gov.hmrc.domain.Nino import uk.gov.hmrc.http.{HeaderCarrier, UpstreamErrorResponse} @@ -86,8 +87,14 @@ class IncomeService @Inject() ( def taxCodeIncomes(nino: Nino, year: TaxYear)(implicit hc: HeaderCarrier, request: Request[_] + ): Future[Seq[TaxCodeIncome]] = + taxCodeIncomes(taxAccountConnector.taxAccount(nino, year), nino, year) + + def taxCodeIncomes(taxAccountDetails: Future[JsValue], nino: Nino, year: TaxYear)(implicit + hc: HeaderCarrier, + request: Request[_] ): Future[Seq[TaxCodeIncome]] = { - lazy val eventualIncomes = taxCodeIncomeHelper.fetchTaxCodeIncomes(nino, year) + lazy val eventualIncomes = taxCodeIncomeHelper.fetchTaxCodeIncomes(taxAccountDetails) lazy val eventualEmployments = employmentService .employmentsAsEitherT(nino, year) .leftMap { error => diff --git a/app/uk/gov/hmrc/tai/service/TaxAccountSummaryService.scala b/app/uk/gov/hmrc/tai/service/TaxAccountSummaryService.scala index 4d0d51b5f..4f959c15b 100644 --- a/app/uk/gov/hmrc/tai/service/TaxAccountSummaryService.scala +++ b/app/uk/gov/hmrc/tai/service/TaxAccountSummaryService.scala @@ -17,11 +17,13 @@ package uk.gov.hmrc.tai.service import com.google.inject.{Inject, Singleton} +import play.api.libs.json.JsValue import play.api.mvc.Request import uk.gov.hmrc.domain.Nino import uk.gov.hmrc.http.HeaderCarrier +import uk.gov.hmrc.tai.connectors.TaxAccountConnector +import uk.gov.hmrc.tai.model.domain.* import uk.gov.hmrc.tai.model.domain.calculation.CodingComponent -import uk.gov.hmrc.tai.model.domain._ import uk.gov.hmrc.tai.model.tai.TaxYear import uk.gov.hmrc.tai.service.helper.TaxAccountHelper @@ -33,7 +35,8 @@ class TaxAccountSummaryService @Inject() ( codingComponentService: CodingComponentService, incomeService: IncomeService, totalTaxService: TotalTaxService, - taxAccountHelper: TaxAccountHelper + taxAccountHelper: TaxAccountHelper, + taxAccountConnector: TaxAccountConnector )(implicit ec: ExecutionContext ) { @@ -41,18 +44,16 @@ class TaxAccountSummaryService @Inject() ( def taxAccountSummary(nino: Nino, year: TaxYear)(implicit hc: HeaderCarrier, request: Request[_] - ): Future[TaxAccountSummary] = - // This is really bad if for some reason the cache does not work properly. - // It generates a large number of http calls to the same API. - // The calls are sequential so there is no race condition to the cache. - // todo: refactor all different calls to taxAccount connector into a single call and the proper reads. + ): Future[TaxAccountSummary] = { + val taxAccountDetails: Future[JsValue] = taxAccountConnector.taxAccount(nino, year) + for { - totalEstimatedTax <- taxAccountHelper.totalEstimatedTax(nino, year) - taxFreeAmountComponents <- codingComponentService.codingComponents(nino, year) - taxCodeIncomes <- incomeService.taxCodeIncomes(nino, year) - totalTax <- totalTaxService.totalTax(nino, year) - taxFreeAllowance <- totalTaxService.taxFreeAllowance(nino, year) - date <- taxAccountHelper.dateOfTaxAccount(nino, year) + totalEstimatedTax <- taxAccountHelper.totalEstimatedTax(taxAccountDetails) + taxFreeAmountComponents <- codingComponentService.codingComponents(taxAccountDetails) + taxCodeIncomes <- incomeService.taxCodeIncomes(taxAccountDetails, nino, year) + totalTax <- totalTaxService.totalTax(taxAccountDetails) + taxFreeAllowance <- totalTaxService.taxFreeAllowance(taxAccountDetails) + date <- taxAccountHelper.dateOfTaxAccount(taxAccountDetails) } yield { val taxFreeAmount = taxFreeAmountCalculation(taxFreeAmountComponents) @@ -75,6 +76,7 @@ class TaxAccountSummaryService @Inject() ( date ) } + } private[service] def taxFreeAmountCalculation(codingComponents: Seq[CodingComponent]): BigDecimal = codingComponents.foldLeft(BigDecimal(0))((total: BigDecimal, component: CodingComponent) => diff --git a/app/uk/gov/hmrc/tai/service/TotalTaxService.scala b/app/uk/gov/hmrc/tai/service/TotalTaxService.scala index b9a72ad5e..2246ca69a 100644 --- a/app/uk/gov/hmrc/tai/service/TotalTaxService.scala +++ b/app/uk/gov/hmrc/tai/service/TotalTaxService.scala @@ -17,6 +17,7 @@ package uk.gov.hmrc.tai.service import com.google.inject.{Inject, Singleton} +import play.api.libs.json.JsValue import uk.gov.hmrc.domain.Nino import uk.gov.hmrc.http.HeaderCarrier import uk.gov.hmrc.tai.connectors.TaxAccountConnector @@ -32,11 +33,13 @@ class TotalTaxService @Inject() ( taxAccountConnector: TaxAccountConnector, taxAccountHelper: TaxAccountHelper )(implicit ec: ExecutionContext) { - def totalTax(nino: Nino, year: TaxYear)(implicit hc: HeaderCarrier): Future[TotalTax] = { - val taxAccountDetails = taxAccountConnector.taxAccount(nino, year) + def totalTax(nino: Nino, year: TaxYear)(implicit hc: HeaderCarrier): Future[TotalTax] = + totalTax(taxAccountConnector.taxAccount(nino, year)) + + def totalTax(taxAccountDetails: Future[JsValue]): Future[TotalTax] = for { incomeCategories <- taxAccountDetails.map(_.as[Seq[IncomeCategory]](TotalTaxHipReads.incomeCategorySeqReads)) - totalTaxAmount <- taxAccountHelper.totalEstimatedTax(nino, year) + totalTaxAmount <- taxAccountHelper.totalEstimatedTax(taxAccountDetails) reliefsGivingBackTax <- taxAccountHelper.reliefsGivingBackTaxComponents(taxAccountDetails) otherTaxDue <- taxAccountHelper.otherTaxDueComponents(taxAccountDetails) alreadyTaxedAtSource <- taxAccountHelper.alreadyTaxedAtSourceComponents(taxAccountDetails) @@ -51,10 +54,7 @@ class TotalTaxService @Inject() ( taxOnOtherIncome, taxReliefComponents ) - } - def taxFreeAllowance(nino: Nino, year: TaxYear)(implicit hc: HeaderCarrier): Future[BigDecimal] = - taxAccountConnector - .taxAccount(nino, year) - .map(_.as[BigDecimal](TotalTaxHipReads.taxFreeAllowanceReads)) + def taxFreeAllowance(taxAccountDetails: Future[JsValue]): Future[BigDecimal] = + taxAccountDetails.map(_.as[BigDecimal](TotalTaxHipReads.taxFreeAllowanceReads)) } diff --git a/app/uk/gov/hmrc/tai/service/helper/TaxAccountHelper.scala b/app/uk/gov/hmrc/tai/service/helper/TaxAccountHelper.scala index e245757a9..b8f1822e9 100644 --- a/app/uk/gov/hmrc/tai/service/helper/TaxAccountHelper.scala +++ b/app/uk/gov/hmrc/tai/service/helper/TaxAccountHelper.scala @@ -38,7 +38,10 @@ class TaxAccountHelper @Inject() (taxAccountConnector: TaxAccountConnector)(impl ec: ExecutionContext ) extends Logging { - def dateOfTaxAccount(nino: Nino, year: TaxYear)(implicit hc: HeaderCarrier): Future[Option[LocalDate]] = { + def dateOfTaxAccount(nino: Nino, year: TaxYear)(implicit hc: HeaderCarrier): Future[Option[LocalDate]] = + dateOfTaxAccount(taxAccountConnector.taxAccount(nino, year)) + + def dateOfTaxAccount(taxAccountDetails: Future[JsValue]): Future[Option[LocalDate]] = { val dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd") val localDateOptionReads: Reads[Option[LocalDate]] = Reads[Option[LocalDate]] { jsValue => @@ -58,19 +61,16 @@ class TaxAccountHelper @Inject() (taxAccountConnector: TaxAccountConnector)(impl } } - taxAccountConnector - .taxAccount(nino, year) - .map { taxAccount => - (taxAccount \ "date").asOpt[Option[LocalDate]](localDateOptionReads).flatten - } + taxAccountDetails.map { taxAccount => + (taxAccount \ "date").asOpt[Option[LocalDate]](localDateOptionReads).flatten + } } - def totalEstimatedTax(nino: Nino, year: TaxYear)(implicit hc: HeaderCarrier): Future[BigDecimal] = { + def totalEstimatedTax(taxAccountDetails: Future[JsValue]): Future[BigDecimal] = { val componentTypesCanAffectTotalEst: Seq[TaxComponentType] = Seq(UnderPaymentFromPreviousYear, OutstandingDebt, EstimatedTaxYouOweThisYear) - taxAccountConnector - .taxAccount(nino, year) + taxAccountDetails .flatMap { taxAccount => val totalTax = taxAccount.as[BigDecimal](TaxOnOtherIncomeHipReads.taxAccountSummaryReads) diff --git a/app/uk/gov/hmrc/tai/service/helper/TaxCodeIncomeHelper.scala b/app/uk/gov/hmrc/tai/service/helper/TaxCodeIncomeHelper.scala index 171df256a..82e37e17e 100644 --- a/app/uk/gov/hmrc/tai/service/helper/TaxCodeIncomeHelper.scala +++ b/app/uk/gov/hmrc/tai/service/helper/TaxCodeIncomeHelper.scala @@ -17,6 +17,7 @@ package uk.gov.hmrc.tai.service.helper import com.google.inject.{Inject, Singleton} +import play.api.libs.json.JsValue import uk.gov.hmrc.domain.Nino import uk.gov.hmrc.http.{HeaderCarrier, NotFoundException} import uk.gov.hmrc.tai.connectors.TaxAccountConnector @@ -31,9 +32,10 @@ class TaxCodeIncomeHelper @Inject() ( taxAccountConnector: TaxAccountConnector )(implicit ec: ExecutionContext) { def fetchTaxCodeIncomes(nino: Nino, year: TaxYear)(implicit hc: HeaderCarrier): Future[Seq[TaxCodeIncome]] = - taxAccountConnector - .taxAccount(nino, year) - .map(_.as[Seq[TaxCodeIncome]](TaxCodeIncomeHipReads.taxCodeIncomeSourcesReads)) + fetchTaxCodeIncomes(taxAccountConnector.taxAccount(nino, year)) + + def fetchTaxCodeIncomes(taxAccountDetails: Future[JsValue]): Future[Seq[TaxCodeIncome]] = + taxAccountDetails.map(_.as[Seq[TaxCodeIncome]](TaxCodeIncomeHipReads.taxCodeIncomeSourcesReads)) def incomeAmountForEmploymentId(nino: Nino, year: TaxYear, employmentId: Int)(implicit hc: HeaderCarrier diff --git a/test/uk/gov/hmrc/tai/service/IncomeServiceSpec.scala b/test/uk/gov/hmrc/tai/service/IncomeServiceSpec.scala index edf144046..6f3cac79d 100644 --- a/test/uk/gov/hmrc/tai/service/IncomeServiceSpec.scala +++ b/test/uk/gov/hmrc/tai/service/IncomeServiceSpec.scala @@ -169,13 +169,19 @@ class IncomeServiceSpec @Inject (config: IncomeDetailsConfig) extends BaseSpec { val mockEmploymentService = mock[EmploymentService] val mockTaxCodeIncomeHelper = mock[TaxCodeIncomeHelper] - when(mockTaxCodeIncomeHelper.fetchTaxCodeIncomes(any(), any())(any())) + val mockTaxAccountConnector = mock[TaxAccountConnector] + when(mockTaxAccountConnector.taxAccount(any(), any())(any())).thenReturn(Future.successful(Json.obj())) + when(mockTaxCodeIncomeHelper.fetchTaxCodeIncomes(any[Future[JsValue]]())) .thenReturn(Future.successful(taxCodeIncomes)) when(mockEmploymentService.employmentsAsEitherT(any[Nino], any[TaxYear])(any[HeaderCarrier], any())) .thenReturn(EitherT.rightT(Employments(Seq(employment, employment2), None))) - val sut = createSUT(employmentService = mockEmploymentService, taxCodeIncomeHelper = mockTaxCodeIncomeHelper) + val sut = createSUT( + employmentService = mockEmploymentService, + taxCodeIncomeHelper = mockTaxCodeIncomeHelper, + taxAccountConnector = mockTaxAccountConnector + ) val result = sut.taxCodeIncomes(nino, TaxYear())(HeaderCarrier(), FakeRequest()).futureValue result mustBe taxCodeIncomes.map(_.copy(status = Ceased)) @@ -213,13 +219,19 @@ class IncomeServiceSpec @Inject (config: IncomeDetailsConfig) extends BaseSpec { val mockEmploymentService = mock[EmploymentService] val mockTaxCodeIncomeHelper = mock[TaxCodeIncomeHelper] - when(mockTaxCodeIncomeHelper.fetchTaxCodeIncomes(any(), any())(any())) + val mockTaxAccountConnector = mock[TaxAccountConnector] + when(mockTaxAccountConnector.taxAccount(any(), any())(any())).thenReturn(Future.successful(Json.obj())) + when(mockTaxCodeIncomeHelper.fetchTaxCodeIncomes(any[Future[JsValue]]())) .thenReturn(Future.successful(taxCodeIncomes)) when(mockEmploymentService.employmentsAsEitherT(any[Nino], any[TaxYear])(any[HeaderCarrier], any())) .thenReturn(EitherT.rightT(Employments(Seq.empty, None))) - val sut = createSUT(employmentService = mockEmploymentService, taxCodeIncomeHelper = mockTaxCodeIncomeHelper) + val sut = createSUT( + employmentService = mockEmploymentService, + taxCodeIncomeHelper = mockTaxCodeIncomeHelper, + taxAccountConnector = mockTaxAccountConnector + ) val result = sut.taxCodeIncomes(nino, TaxYear())(HeaderCarrier(), FakeRequest()).futureValue result mustBe taxCodeIncomes @@ -257,13 +269,19 @@ class IncomeServiceSpec @Inject (config: IncomeDetailsConfig) extends BaseSpec { val mockEmploymentService = mock[EmploymentService] val mockTaxCodeIncomeHelper = mock[TaxCodeIncomeHelper] - when(mockTaxCodeIncomeHelper.fetchTaxCodeIncomes(any(), any())(any())) + val mockTaxAccountConnector = mock[TaxAccountConnector] + when(mockTaxAccountConnector.taxAccount(any(), any())(any())).thenReturn(Future.successful(Json.obj())) + when(mockTaxCodeIncomeHelper.fetchTaxCodeIncomes(any[Future[JsValue]]())) .thenReturn(Future.successful(taxCodeIncomes)) when(mockEmploymentService.employmentsAsEitherT(any[Nino], any[TaxYear])(any[HeaderCarrier], any())) .thenReturn(EitherT.leftT(UpstreamErrorResponse("not found", NOT_FOUND))) - val sut = createSUT(employmentService = mockEmploymentService, taxCodeIncomeHelper = mockTaxCodeIncomeHelper) + val sut = createSUT( + employmentService = mockEmploymentService, + taxCodeIncomeHelper = mockTaxCodeIncomeHelper, + taxAccountConnector = mockTaxAccountConnector + ) val result = sut.taxCodeIncomes(nino, TaxYear())(HeaderCarrier(), FakeRequest()).futureValue result mustBe taxCodeIncomes diff --git a/test/uk/gov/hmrc/tai/service/TaxAccountSummaryServiceSpec.scala b/test/uk/gov/hmrc/tai/service/TaxAccountSummaryServiceSpec.scala index 0f71afb20..b6398aa30 100644 --- a/test/uk/gov/hmrc/tai/service/TaxAccountSummaryServiceSpec.scala +++ b/test/uk/gov/hmrc/tai/service/TaxAccountSummaryServiceSpec.scala @@ -18,7 +18,9 @@ package uk.gov.hmrc.tai.service import org.mockito.ArgumentMatchers.{any, eq as meq} import org.mockito.Mockito.when +import play.api.libs.json.{JsValue, Json} import play.api.test.FakeRequest +import uk.gov.hmrc.tai.connectors.TaxAccountConnector import uk.gov.hmrc.tai.model.domain.* import uk.gov.hmrc.tai.model.domain.calculation.* import uk.gov.hmrc.tai.model.domain.income.{Live, OtherBasisOperation, TaxCodeIncome} @@ -42,12 +44,21 @@ class TaxAccountSummaryServiceSpec extends BaseSpec { private val mockIncomeService = mock[IncomeService] private val mockTotalTaxService = mock[TotalTaxService] private val mockTaxAccountHelper = mock[TaxAccountHelper] + private val mockTaxAccountConnector = mock[TaxAccountConnector] + + override protected def beforeEach(): Unit = { + super.beforeEach() + when(mockTaxAccountConnector.taxAccount(any(), any())(any())) + .thenReturn(Future.successful(Json.obj())) + () + } private def createSUT() = new TaxAccountSummaryService( mockCodingComponentService, mockIncomeService, mockTotalTaxService, - mockTaxAccountHelper + mockTaxAccountHelper, + mockTaxAccountConnector ) "taxFreeAmountCalculation" must { @@ -131,17 +142,18 @@ class TaxAccountSummaryServiceSpec extends BaseSpec { ) ) - when(mockCodingComponentService.codingComponents(meq(nino), any())(any())) + when(mockCodingComponentService.codingComponents(any[Future[JsValue]]())) .thenReturn(Future.successful(codingComponents)) - when(mockIncomeService.taxCodeIncomes(meq(nino), any())(any(), any())) + when(mockIncomeService.taxCodeIncomes(any[Future[JsValue]](), meq(nino), any())(any(), any())) .thenReturn(Future.successful(taxCodeIncomes)) - when(mockTaxAccountHelper.totalEstimatedTax(meq(nino), any())(any())) + when(mockTaxAccountHelper.totalEstimatedTax(any[Future[JsValue]]())) .thenReturn(Future.successful(BigDecimal(1111))) - when(mockTotalTaxService.totalTax(any(), any())(any())).thenReturn(Future.successful(totalTaxDetails)) - when(mockTotalTaxService.taxFreeAllowance(any(), any())(any())).thenReturn(Future.successful(BigDecimal(100))) - when(mockTaxAccountHelper.dateOfTaxAccount(any(), any())(any())).thenReturn( + when(mockTotalTaxService.totalTax(any[Future[JsValue]]())).thenReturn(Future.successful(totalTaxDetails)) + when(mockTotalTaxService.taxFreeAllowance(any[Future[JsValue]]())) + .thenReturn(Future.successful(BigDecimal(100))) + when(mockTaxAccountHelper.dateOfTaxAccount(any[Future[JsValue]]())).thenReturn( Future.successful(Some(LocalDate.of(2026, 1, 1))) ) @@ -194,16 +206,17 @@ class TaxAccountSummaryServiceSpec extends BaseSpec { ) ) - when(mockCodingComponentService.codingComponents(meq(nino), any())(any())) + when(mockCodingComponentService.codingComponents(any[Future[JsValue]]())) .thenReturn(Future.successful(codingComponents)) - when(mockIncomeService.taxCodeIncomes(meq(nino), any())(any(), any())) + when(mockIncomeService.taxCodeIncomes(any[Future[JsValue]](), meq(nino), any())(any(), any())) .thenReturn(Future.successful(taxCodeIncomes)) - when(mockTaxAccountHelper.totalEstimatedTax(meq(nino), any())(any())) + when(mockTaxAccountHelper.totalEstimatedTax(any[Future[JsValue]]())) .thenReturn(Future.successful(BigDecimal(1111))) - when(mockTotalTaxService.totalTax(any(), any())(any())).thenReturn(Future.successful(totalTaxDetails)) - when(mockTotalTaxService.taxFreeAllowance(any(), any())(any())).thenReturn(Future.successful(BigDecimal(100))) - when(mockTaxAccountHelper.dateOfTaxAccount(any(), any())(any())).thenReturn( + when(mockTotalTaxService.totalTax(any[Future[JsValue]]())).thenReturn(Future.successful(totalTaxDetails)) + when(mockTotalTaxService.taxFreeAllowance(any[Future[JsValue]]())) + .thenReturn(Future.successful(BigDecimal(100))) + when(mockTaxAccountHelper.dateOfTaxAccount(any[Future[JsValue]]())).thenReturn( Future.successful(Some(LocalDate.of(2026, 1, 1))) ) @@ -246,17 +259,18 @@ class TaxAccountSummaryServiceSpec extends BaseSpec { ) ) - when(mockCodingComponentService.codingComponents(meq(nino), any())(any())) + when(mockCodingComponentService.codingComponents(any[Future[JsValue]]())) .thenReturn(Future.successful(codingComponents)) - when(mockIncomeService.taxCodeIncomes(meq(nino), any())(any(), any())) + when(mockIncomeService.taxCodeIncomes(any[Future[JsValue]](), meq(nino), any())(any(), any())) .thenReturn(Future.successful(taxCodeIncomes)) - when(mockTaxAccountHelper.totalEstimatedTax(meq(nino), any())(any())) + when(mockTaxAccountHelper.totalEstimatedTax(any[Future[JsValue]]())) .thenReturn(Future.successful(BigDecimal(1111))) - when(mockTotalTaxService.totalTax(any(), any())(any())).thenReturn(Future.successful(totalTaxDetails)) - when(mockTotalTaxService.taxFreeAllowance(any(), any())(any())).thenReturn(Future.successful(BigDecimal(100))) - when(mockTaxAccountHelper.dateOfTaxAccount(any(), any())(any())).thenReturn( + when(mockTotalTaxService.totalTax(any[Future[JsValue]]())).thenReturn(Future.successful(totalTaxDetails)) + when(mockTotalTaxService.taxFreeAllowance(any[Future[JsValue]]())) + .thenReturn(Future.successful(BigDecimal(100))) + when(mockTaxAccountHelper.dateOfTaxAccount(any[Future[JsValue]]())).thenReturn( Future.successful(Some(LocalDate.of(2026, 1, 1))) ) @@ -309,18 +323,19 @@ class TaxAccountSummaryServiceSpec extends BaseSpec { ) ) - when(mockTaxAccountHelper.totalEstimatedTax(meq(nino), any())(any())) + when(mockTaxAccountHelper.totalEstimatedTax(any[Future[JsValue]]())) .thenReturn(Future.successful(BigDecimal(1111))) - when(mockCodingComponentService.codingComponents(meq(nino), any())(any())) + when(mockCodingComponentService.codingComponents(any[Future[JsValue]]())) .thenReturn(Future.successful(taxFreeAmountComponents)) - when(mockIncomeService.taxCodeIncomes(meq(nino), any())(any(), any())) + when(mockIncomeService.taxCodeIncomes(any[Future[JsValue]](), meq(nino), any())(any(), any())) .thenReturn(Future.successful(taxCodeIncomes)) - when(mockTotalTaxService.totalTax(any(), any())(any())).thenReturn(Future.successful(totalTaxDetails)) - when(mockTotalTaxService.taxFreeAllowance(any(), any())(any())).thenReturn(Future.successful(BigDecimal(10000))) - when(mockTaxAccountHelper.dateOfTaxAccount(any(), any())(any())).thenReturn( + when(mockTotalTaxService.totalTax(any[Future[JsValue]]())).thenReturn(Future.successful(totalTaxDetails)) + when(mockTotalTaxService.taxFreeAllowance(any[Future[JsValue]]())) + .thenReturn(Future.successful(BigDecimal(10000))) + when(mockTaxAccountHelper.dateOfTaxAccount(any[Future[JsValue]]())).thenReturn( Future.successful(Some(LocalDate.of(2026, 1, 1))) ) @@ -344,16 +359,16 @@ class TaxAccountSummaryServiceSpec extends BaseSpec { val taxFreeAmountComponents = Seq( CodingComponent(PersonalAllowancePA, Some(234), BigDecimal(5000), "PersonalAllowancePA") ) - when(mockCodingComponentService.codingComponents(meq(nino), any())(any())) + when(mockCodingComponentService.codingComponents(any[Future[JsValue]]())) .thenReturn(Future.successful(taxFreeAmountComponents)) - when(mockIncomeService.taxCodeIncomes(meq(nino), any())(any(), any())) + when(mockIncomeService.taxCodeIncomes(any[Future[JsValue]](), meq(nino), any())(any(), any())) .thenReturn(Future.successful(Seq.empty[TaxCodeIncome])) - when(mockTaxAccountHelper.totalEstimatedTax(meq(nino), any())(any())) + when(mockTaxAccountHelper.totalEstimatedTax(any[Future[JsValue]]())) .thenReturn(Future.successful(BigDecimal(1111))) - when(mockTaxAccountHelper.dateOfTaxAccount(any(), any())(any())).thenReturn( + when(mockTaxAccountHelper.dateOfTaxAccount(any[Future[JsValue]]())).thenReturn( Future.successful(Some(LocalDate.of(2026, 1, 1))) ) @@ -390,8 +405,9 @@ class TaxAccountSummaryServiceSpec extends BaseSpec { IncomeCategory(UkDividendsIncomeCategory, BigDecimal(0), BigDecimal(6000), BigDecimal(0), Seq.empty[TaxBand]) ) val totalTax = TotalTax(0, incomeCategories, None, None, None) - when(mockTotalTaxService.totalTax(any(), any())(any())).thenReturn(Future.successful(totalTax)) - when(mockTotalTaxService.taxFreeAllowance(any(), any())(any())).thenReturn(Future.successful(BigDecimal(1000))) + when(mockTotalTaxService.totalTax(any[Future[JsValue]]())).thenReturn(Future.successful(totalTax)) + when(mockTotalTaxService.taxFreeAllowance(any[Future[JsValue]]())) + .thenReturn(Future.successful(BigDecimal(1000))) val result = createSUT().taxAccountSummary(nino, TaxYear())(implicitly, FakeRequest()).futureValue @@ -405,21 +421,21 @@ class TaxAccountSummaryServiceSpec extends BaseSpec { CodingComponent(GiftAidPayments, Some(234), BigDecimal(5000), "GiftAid") ) - when(mockCodingComponentService.codingComponents(meq(nino), any())(any())) + when(mockCodingComponentService.codingComponents(any[Future[JsValue]]())) .thenReturn(Future.successful(taxFreeAmountComponents)) - when(mockIncomeService.taxCodeIncomes(meq(nino), any())(any(), any())) + when(mockIncomeService.taxCodeIncomes(any[Future[JsValue]](), meq(nino), any())(any(), any())) .thenReturn(Future.successful(Seq.empty[TaxCodeIncome])) - when(mockTaxAccountHelper.totalEstimatedTax(meq(nino), any())(any())) + when(mockTaxAccountHelper.totalEstimatedTax(any[Future[JsValue]]())) .thenReturn(Future.successful(BigDecimal(1111))) val incomeCategories = Seq( IncomeCategory(NonSavingsIncomeCategory, BigDecimal(0), BigDecimal(1000), BigDecimal(0), Seq.empty[TaxBand]) ) val totalTax = TotalTax(BigDecimal(0), incomeCategories, None, None, None) - when(mockTotalTaxService.totalTax(any(), any())(any())).thenReturn(Future.successful(totalTax)) - when(mockTotalTaxService.taxFreeAllowance(any(), any())(any())).thenReturn(Future.successful(BigDecimal(0))) + when(mockTotalTaxService.totalTax(any[Future[JsValue]]())).thenReturn(Future.successful(totalTax)) + when(mockTotalTaxService.taxFreeAllowance(any[Future[JsValue]]())).thenReturn(Future.successful(BigDecimal(0))) val result = createSUT().taxAccountSummary(nino, TaxYear())(implicitly, FakeRequest()).futureValue @@ -432,21 +448,22 @@ class TaxAccountSummaryServiceSpec extends BaseSpec { val taxFreeAmountComponents = Seq( CodingComponent(PersonalAllowancePA, Some(234), BigDecimal(11500), "PersonalAllowancePA") ) - when(mockCodingComponentService.codingComponents(meq(nino), any())(any())) + when(mockCodingComponentService.codingComponents(any[Future[JsValue]]())) .thenReturn(Future.successful(taxFreeAmountComponents)) - when(mockIncomeService.taxCodeIncomes(meq(nino), any())(any(), any())) + when(mockIncomeService.taxCodeIncomes(any[Future[JsValue]](), meq(nino), any())(any(), any())) .thenReturn(Future.successful(Seq.empty[TaxCodeIncome])) - when(mockTaxAccountHelper.totalEstimatedTax(meq(nino), any())(any())) + when(mockTaxAccountHelper.totalEstimatedTax(any[Future[JsValue]]())) .thenReturn(Future.successful(BigDecimal(0))) val incomeCategories = Seq( IncomeCategory(NonSavingsIncomeCategory, BigDecimal(0), BigDecimal(0), BigDecimal(8000), Seq.empty[TaxBand]) ) val totalTax = TotalTax(0, incomeCategories, None, None, None) - when(mockTotalTaxService.totalTax(any(), any())(any())).thenReturn(Future.successful(totalTax)) - when(mockTotalTaxService.taxFreeAllowance(any(), any())(any())).thenReturn(Future.successful(BigDecimal(11500))) + when(mockTotalTaxService.totalTax(any[Future[JsValue]]())).thenReturn(Future.successful(totalTax)) + when(mockTotalTaxService.taxFreeAllowance(any[Future[JsValue]]())) + .thenReturn(Future.successful(BigDecimal(11500))) val result = createSUT().taxAccountSummary(nino, TaxYear())(implicitly, FakeRequest()).futureValue diff --git a/test/uk/gov/hmrc/tai/service/TotalTaxServiceSpec.scala b/test/uk/gov/hmrc/tai/service/TotalTaxServiceSpec.scala index 0cb9cef97..ace9d09a6 100644 --- a/test/uk/gov/hmrc/tai/service/TotalTaxServiceSpec.scala +++ b/test/uk/gov/hmrc/tai/service/TotalTaxServiceSpec.scala @@ -18,7 +18,7 @@ package uk.gov.hmrc.tai.service import org.mockito.ArgumentMatchers.{any, eq as meq} import org.mockito.Mockito.{reset, when} -import play.api.libs.json.{JsObject, Json} +import play.api.libs.json.{JsObject, JsValue, Json} import uk.gov.hmrc.tai.connectors.TaxAccountConnector import uk.gov.hmrc.tai.model.domain.calculation.IncomeCategory import uk.gov.hmrc.tai.model.domain.taxAdjustments.* @@ -106,7 +106,7 @@ class TotalTaxServiceSpec extends BaseSpec { "totalTax" must { "return the income categories that is coming from TaxAccountConnector" in { - when(mockTaxAccountHelper.totalEstimatedTax(meq(nino), meq(TaxYear()))(any())) + when(mockTaxAccountHelper.totalEstimatedTax(any[Future[JsValue]]())) .thenReturn(Future.successful(BigDecimal(0))) when(mockTaxAccountHelper.reliefsGivingBackTaxComponents(any())).thenReturn(Future.successful(None)) when(mockTaxAccountHelper.otherTaxDueComponents(any())).thenReturn(Future.successful(None)) @@ -125,7 +125,7 @@ class TotalTaxServiceSpec extends BaseSpec { } "return amount that is coming from totalEstimatedTax" in { - when(mockTaxAccountHelper.totalEstimatedTax(meq(nino), meq(TaxYear()))(any())) + when(mockTaxAccountHelper.totalEstimatedTax(any[Future[JsValue]]())) .thenReturn(Future.successful(BigDecimal(1000))) when(mockTaxAccountHelper.reliefsGivingBackTaxComponents(any())).thenReturn(Future.successful(None)) when(mockTaxAccountHelper.otherTaxDueComponents(any())).thenReturn(Future.successful(None)) @@ -142,7 +142,7 @@ class TotalTaxServiceSpec extends BaseSpec { } "return reliefs giving back tax adjustment component" in { - when(mockTaxAccountHelper.totalEstimatedTax(meq(nino), meq(TaxYear()))(any())) + when(mockTaxAccountHelper.totalEstimatedTax(any[Future[JsValue]]())) .thenReturn(Future.successful(BigDecimal(0))) val adjustment = TaxAdjustment(100, Seq(TaxAdjustmentComponent(EnterpriseInvestmentSchemeRelief, 100))) when(mockTaxAccountHelper.reliefsGivingBackTaxComponents(any())).thenReturn( @@ -161,7 +161,7 @@ class TotalTaxServiceSpec extends BaseSpec { } "return other tax due component" in { - when(mockTaxAccountHelper.totalEstimatedTax(meq(nino), meq(TaxYear()))(any())) + when(mockTaxAccountHelper.totalEstimatedTax(any[Future[JsValue]]())) .thenReturn(Future.successful(BigDecimal(0))) val adjustment = TaxAdjustment(100, Seq(TaxAdjustmentComponent(ExcessGiftAidTax, 100))) when(mockTaxAccountHelper.reliefsGivingBackTaxComponents(any())).thenReturn(Future.successful(None)) @@ -176,7 +176,7 @@ class TotalTaxServiceSpec extends BaseSpec { } "return already taxed at source component" in { - when(mockTaxAccountHelper.totalEstimatedTax(meq(nino), meq(TaxYear()))(any())) + when(mockTaxAccountHelper.totalEstimatedTax(any[Future[JsValue]]())) .thenReturn(Future.successful(BigDecimal(0))) val adjustment = TaxAdjustment(100, Seq(TaxAdjustmentComponent(TaxOnBankBSInterest, 100))) when(mockTaxAccountHelper.reliefsGivingBackTaxComponents(any())).thenReturn(Future.successful(None)) @@ -191,7 +191,7 @@ class TotalTaxServiceSpec extends BaseSpec { } "return tax on other income" in { - when(mockTaxAccountHelper.totalEstimatedTax(meq(nino), meq(TaxYear()))(any())) + when(mockTaxAccountHelper.totalEstimatedTax(any[Future[JsValue]]())) .thenReturn(Future.successful(BigDecimal(0))) when(mockTaxAccountHelper.reliefsGivingBackTaxComponents(any())).thenReturn(Future.successful(None)) when(mockTaxAccountHelper.otherTaxDueComponents(any())).thenReturn(Future.successful(None)) @@ -206,7 +206,7 @@ class TotalTaxServiceSpec extends BaseSpec { "return tax relief components" in { val taxReliefComponents = TaxAdjustment(100, Seq(TaxAdjustmentComponent(PersonalPensionPaymentRelief, 100))) - when(mockTaxAccountHelper.totalEstimatedTax(meq(nino), meq(TaxYear()))(any())) + when(mockTaxAccountHelper.totalEstimatedTax(any[Future[JsValue]]())) .thenReturn(Future.successful(BigDecimal(0))) when(mockTaxAccountHelper.reliefsGivingBackTaxComponents(any())).thenReturn(Future.successful(None)) when(mockTaxAccountHelper.otherTaxDueComponents(any())).thenReturn(Future.successful(None)) @@ -222,7 +222,7 @@ class TotalTaxServiceSpec extends BaseSpec { "taxFreeAllowance" must { "return tax free allowance amount" in { - val result = sut.taxFreeAllowance(nino, TaxYear()).futureValue + val result = sut.taxFreeAllowance(Future.successful(incomeCategories)).futureValue result mustBe 100 } diff --git a/test/uk/gov/hmrc/tai/service/helper/TaxAccountHelperSpec.scala b/test/uk/gov/hmrc/tai/service/helper/TaxAccountHelperSpec.scala index 341d1a908..a0cb9f078 100644 --- a/test/uk/gov/hmrc/tai/service/helper/TaxAccountHelperSpec.scala +++ b/test/uk/gov/hmrc/tai/service/helper/TaxAccountHelperSpec.scala @@ -126,9 +126,7 @@ class TaxAccountHelperSpec extends BaseSpec { ) ) val jsonWithUnderPayments = createJsonWithDeductions(underpaymentDeduction) - when(mockTaxAccountConnector.taxAccount(any(), any())(any())) - .thenReturn(Future.successful(jsonWithUnderPayments)) - val result = createSUT().totalEstimatedTax(nino, TaxYear()).futureValue + val result = createSUT().totalEstimatedTax(Future.successful(jsonWithUnderPayments)).futureValue result mustBe BigDecimal(1171) } @@ -141,10 +139,8 @@ class TaxAccountHelperSpec extends BaseSpec { ) ) val jsonWithOutstandingDebt = createJsonWithDeductions(outstandingDebtDeduction) - when(mockTaxAccountConnector.taxAccount(any(), any())(any())) - .thenReturn(Future.successful(jsonWithOutstandingDebt)) - val result = createSUT().totalEstimatedTax(nino, TaxYear()).futureValue + val result = createSUT().totalEstimatedTax(Future.successful(jsonWithOutstandingDebt)).futureValue result mustBe BigDecimal(1171) } @@ -157,10 +153,8 @@ class TaxAccountHelperSpec extends BaseSpec { ) ) val jsonWithEstimatedTaxOwed = createJsonWithDeductions(estimatedTaxOwedDeduction) - when(mockTaxAccountConnector.taxAccount(any(), any())(any())) - .thenReturn(Future.successful(jsonWithEstimatedTaxOwed)) - val result = createSUT().totalEstimatedTax(nino, TaxYear()).futureValue + val result = createSUT().totalEstimatedTax(Future.successful(jsonWithEstimatedTaxOwed)).futureValue result mustBe BigDecimal(1171) } @@ -189,10 +183,8 @@ class TaxAccountHelperSpec extends BaseSpec { ) ) val jsonWithAllAffectingComponents = createJsonWithDeductions(allAffectingDeductions) - when(mockTaxAccountConnector.taxAccount(any(), any())(any())) - .thenReturn(Future.successful(jsonWithAllAffectingComponents)) - val result = createSUT().totalEstimatedTax(nino, TaxYear()).futureValue + val result = createSUT().totalEstimatedTax(Future.successful(jsonWithAllAffectingComponents)).futureValue result mustBe BigDecimal(1371) } } @@ -207,10 +199,8 @@ class TaxAccountHelperSpec extends BaseSpec { ) ) val jsonWithNoEffectingComponent = createJsonWithDeductions(noAffectingDeductions) - when(mockTaxAccountConnector.taxAccount(any(), any())(any())) - .thenReturn(Future.successful(jsonWithNoEffectingComponent)) - val result = createSUT().totalEstimatedTax(nino, TaxYear()).futureValue + val result = createSUT().totalEstimatedTax(Future.successful(jsonWithNoEffectingComponent)).futureValue result mustBe BigDecimal(1071) } }