Skip to content

Commit

Permalink
SASS-8727: save NICs class2 answers (#120)
Browse files Browse the repository at this point in the history
  • Loading branch information
lukastymo authored Jul 30, 2024
1 parent 9373ace commit 303c55d
Show file tree
Hide file tree
Showing 32 changed files with 983 additions and 61 deletions.
1 change: 1 addition & 0 deletions app/config/Module.scala
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class Module extends AbstractModule {
bind(classOf[JourneyAnswersRepository]).to(classOf[MongoJourneyAnswersRepository])
bind(classOf[SelfEmploymentConnector]).to(classOf[SelfEmploymentConnectorImpl])
bind(classOf[JourneyStatusService]).to(classOf[JourneyStatusServiceImpl])
bind(classOf[NICsAnswersService]).to(classOf[NICsAnswersServiceImpl])
()
}

Expand Down
46 changes: 45 additions & 1 deletion app/connectors/SelfEmploymentConnectorImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,21 @@

package connectors

import cats.data.EitherT
import com.typesafe.config.ConfigFactory
import config.AppConfig
import connectors.SelfEmploymentConnector._
import models.common.TaxYear.{asTys, endDate, startDate}
import models.common._
import models.connector.IntegrationContext.IFSHeaderCarrier
import models.connector._
import models.connector.api_1638.RequestSchemaAPI1638
import models.connector.api_1639.SuccessResponseAPI1639
import models.connector.api_1802.request.{CreateAmendSEAnnualSubmissionRequestBody, CreateAmendSEAnnualSubmissionRequestData}
import models.connector.api_1894.request.{CreateSEPeriodSummaryRequestBody, CreateSEPeriodSummaryRequestData}
import models.connector.api_1895.request.{AmendSEPeriodSummaryRequestBody, AmendSEPeriodSummaryRequestData}
import uk.gov.hmrc.http.{HeaderCarrier, HttpClient}
import models.domain.ApiResultT
import uk.gov.hmrc.http.{HeaderCarrier, HttpClient, HttpReads}
import utils.Logging

import javax.inject.{Inject, Singleton}
Expand All @@ -43,6 +47,13 @@ trait SelfEmploymentConnector {
def createSEPeriodSummary(data: CreateSEPeriodSummaryRequestData)(implicit hc: HeaderCarrier, ec: ExecutionContext): Future[Api1894Response]
def amendSEPeriodSummary(data: AmendSEPeriodSummaryRequestData)(implicit hc: HeaderCarrier, ec: ExecutionContext): Future[Api1895Response]
def listSEPeriodSummary(ctx: JourneyContextWithNino)(implicit hc: HeaderCarrier, ec: ExecutionContext): Future[Api1965Response]

def getDisclosuresSubmission(
ctx: JourneyContextWithNino)(implicit hc: HeaderCarrier, ec: ExecutionContext): ApiResultT[Option[SuccessResponseAPI1639]]
def upsertDisclosuresSubmission(ctx: JourneyContextWithNino, data: RequestSchemaAPI1638)(implicit
hc: HeaderCarrier,
ec: ExecutionContext): ApiResultT[Unit]
def deleteDisclosuresSubmission(ctx: JourneyContextWithNino)(implicit hc: HeaderCarrier, ec: ExecutionContext): ApiResultT[Unit]
}

object SelfEmploymentConnector {
Expand All @@ -53,6 +64,8 @@ object SelfEmploymentConnector {
type Api1894Response = ApiResponse[api_1894.response.CreateSEPeriodSummaryResponse]
type Api1895Response = ApiResponse[api_1895.response.AmendSEPeriodSummaryResponse]
type Api1965Response = ApiResponse[api_1965.ListSEPeriodSummariesResponse]
type Api1638Response = ApiResponse[Unit]
type Api1639Response = ApiResponseOption[SuccessResponseAPI1639]
}

@Singleton
Expand All @@ -75,6 +88,9 @@ class SelfEmploymentConnectorImpl @Inject() (http: HttpClient, appConfig: AppCon
private def periodicSummaryDetailUrl(nino: Nino, incomeSourceId: BusinessId, taxYear: TaxYear) =
s"${baseUrl(nino, incomeSourceId, taxYear)}/periodic-summary-detail?from=${startDate(taxYear)}&to=${endDate(taxYear)}"

private def disclosuresSubmissionUrl(nino: Nino, taxYear: TaxYear) =
s"${appConfig.ifsBaseUrl}/income-tax/disclosures/$nino/${taxYear.toYYYY_YY}"

// TODO Move to GetBusinessDetailsConnector
def getBusinesses(idType: IdType, idNumber: String)(implicit hc: HeaderCarrier, ec: ExecutionContext): Future[Api1171Response] = {
val context = mkIFSMetadata(IFSApiName.Api1171, api1171BusinessDetailsUrl(idType, idNumber))
Expand Down Expand Up @@ -117,4 +133,32 @@ class SelfEmploymentConnectorImpl @Inject() (http: HttpClient, appConfig: AppCon
val context = mkIFSMetadata(IFSApiName.Api1803, url)
get[Api1803Response](http, context)
}

def getDisclosuresSubmission(
ctx: JourneyContextWithNino)(implicit hc: HeaderCarrier, ec: ExecutionContext): ApiResultT[Option[SuccessResponseAPI1639]] = {
val url = disclosuresSubmissionUrl(ctx.nino, ctx.taxYear)
val context = mkIFSMetadata(IFSApiName.Api1639, url)
implicit val reads: HttpReads[ApiResponse[Option[SuccessResponseAPI1639]]] = commonGetReads[SuccessResponseAPI1639]

EitherT(get[Api1639Response](http, context))
}

def upsertDisclosuresSubmission(ctx: JourneyContextWithNino, data: RequestSchemaAPI1638)(implicit
hc: HeaderCarrier,
ec: ExecutionContext): ApiResultT[Unit] = {
val url = disclosuresSubmissionUrl(ctx.nino, ctx.taxYear)
val context = mkIFSMetadata(IFSApiName.Api1638, url)
implicit val reads: HttpReads[ApiResponse[Unit]] = commonNoBodyResponse

EitherT(put[RequestSchemaAPI1638, Api1638Response](http, context, data))
}

def deleteDisclosuresSubmission(ctx: JourneyContextWithNino)(implicit hc: HeaderCarrier, ec: ExecutionContext): ApiResultT[Unit] = {
val url = disclosuresSubmissionUrl(ctx.nino, ctx.taxYear)
val context = mkIFSMetadata(IFSApiName.Api1640, url)
implicit val reads: HttpReads[ApiResponse[Unit]] = commonDeleteReads

EitherT(delete(http, context))
}

}
9 changes: 9 additions & 0 deletions app/connectors/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,13 @@ package object connectors {
ConnectorRequestInfo("PUT", context.url, context.api).logRequestWithBody(logger, body)
http.PUT[Req, Resp](context.url, body)(writes, reads, context.enrichedHeaderCarrier, ec)
}

def delete[Resp: HttpReads](http: HttpClient, context: IntegrationContext)(implicit
hc: HeaderCarrier,
ec: ExecutionContext,
logger: Logger): Future[Resp] = {
val reads = implicitly[HttpReads[Resp]]
ConnectorRequestInfo("DELETE", context.url, context.api).logRequest(logger)
http.DELETE[Resp](context.url)(reads, context.enrichedHeaderCarrier, ec)
}
}
14 changes: 13 additions & 1 deletion app/controllers/JourneyAnswersController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import models.frontend.expenses.tailoring.ExpensesTailoring.TotalAmount
import models.frontend.expenses.tailoring.ExpensesTailoringAnswers._
import models.frontend.expenses.workplaceRunningCosts.WorkplaceRunningCostsAnswers
import models.frontend.income.IncomeJourneyAnswers
import models.frontend.nics.NICsAnswers
import play.api.libs.json.Format.GenericFormat
import play.api.libs.json.{Reads, Writes}
import play.api.mvc.{Action, AnyContent, ControllerComponents, Result}
Expand All @@ -72,7 +73,8 @@ class JourneyAnswersController @Inject() (auth: AuthorisedAction,
abroadAnswersService: AbroadAnswersService,
incomeService: IncomeAnswersService,
expensesService: ExpensesAnswersService,
capitalAllowancesService: CapitalAllowancesAnswersService)(implicit ec: ExecutionContext)
capitalAllowancesService: CapitalAllowancesAnswersService,
nicsAnswersService: NICsAnswersService)(implicit ec: ExecutionContext)
extends BackendController(cc)
with Logging {

Expand Down Expand Up @@ -422,4 +424,14 @@ class JourneyAnswersController @Inject() (auth: AuthorisedAction,
handleOptionalApiResult(capitalAllowancesService.getStructuresBuildings(JourneyContextWithNino(taxYear, businessId, user.getMtditid, nino)))
}

def saveNationalInsuranceContributions(taxYear: TaxYear, businessId: BusinessId, nino: Nino): Action[AnyContent] = auth.async { implicit user =>
getBodyWithCtx[NICsAnswers](taxYear, businessId, nino) { (ctx, answers) =>
nicsAnswersService.saveAnswers(ctx, answers).map(_ => NoContent)
}
}

def getNationalInsuranceContributions(taxYear: TaxYear, businessId: BusinessId, nino: Nino): Action[AnyContent] = auth.async { implicit user =>
handleOptionalApiResult(nicsAnswersService.getAnswers(JourneyContextWithNino(taxYear, businessId, user.getMtditid, nino)))
}

}
2 changes: 2 additions & 0 deletions app/models/common/TaxYear.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import java.time.LocalDate

final case class TaxYear(endYear: Int) extends AnyVal {
override def toString: String = endYear.toString

def toYYYY_YY: String = s"${endYear - 1}-${endYear.toString.takeRight(2)}"
}

object TaxYear {
Expand Down
3 changes: 3 additions & 0 deletions app/models/connector/IFSApiName.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ object IFSApiName extends Enum[IFSApiName] {
val values = IndexedSeq[IFSApiName]()

case object Api1171 extends IFSApiName("1171")
case object Api1638 extends IFSApiName("1638")
case object Api1639 extends IFSApiName("1639")
case object Api1640 extends IFSApiName("1640")
case object Api1786 extends IFSApiName("1786")
case object Api1802 extends IFSApiName("1802")
case object Api1803 extends IFSApiName("1803")
Expand Down
66 changes: 66 additions & 0 deletions app/models/connector/api_1638/RequestSchemaAPI1638.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright 2024 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.connector.api_1638

import models.connector.api_1639.SuccessResponseAPI1639
import models.frontend.nics.NICsAnswers
import play.api.libs.json._

/** Represents the Swagger definition for requestSchemaAPI1638.
*/
case class RequestSchemaAPI1638(
taxAvoidance: Option[List[RequestSchemaAPI1638TaxAvoidanceInner]],
class2Nics: Option[RequestSchemaAPI1638Class2Nics]
)

object RequestSchemaAPI1638 {
implicit lazy val requestSchemaAPI1638JsonFormat: Format[RequestSchemaAPI1638] = Json.format[RequestSchemaAPI1638]

/** Some(false) is not possible to set on class2VoluntaryContributions. We cannot send an empty object therefore if there are no other fields we
* have to call DELETE.
*
* @return
* None if the object needs to be DELETED or Some() if it needs to be updated via PUT
*/
def mkRequestBody(answers: NICsAnswers, maybeExistingDisclosures: Option[SuccessResponseAPI1639]): Option[RequestSchemaAPI1638] = {
val existingDisclosures = maybeExistingDisclosures.getOrElse(SuccessResponseAPI1639.empty)

val bodyForPut = RequestSchemaAPI1638(
taxAvoidance = existingDisclosures.taxAvoidance.map { taxAvoidance =>
taxAvoidance.map { taxAvoidanceInner =>
RequestSchemaAPI1638TaxAvoidanceInner(
srn = taxAvoidanceInner.srn,
taxYear = taxAvoidanceInner.taxYear
)
}
},
class2Nics = existingDisclosures.class2Nics.map { class2Nics =>
RequestSchemaAPI1638Class2Nics(
class2VoluntaryContributions = class2Nics.class2VoluntaryContributions
)
}
)

if (answers.class2NICs) {
Some(bodyForPut.copy(class2Nics = Some(RequestSchemaAPI1638Class2Nics(Some(true)))))
} else if (bodyForPut.taxAvoidance.isDefined) {
Some(bodyForPut.copy(class2Nics = None))
} else {
None
}
}
}
29 changes: 29 additions & 0 deletions app/models/connector/api_1638/RequestSchemaAPI1638Class2Nics.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright 2024 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.connector.api_1638

import play.api.libs.json._

/** Voluntary contributions.
*/
case class RequestSchemaAPI1638Class2Nics(
class2VoluntaryContributions: Option[Boolean]
)

object RequestSchemaAPI1638Class2Nics {
implicit lazy val requestSchemaAPI1638Class2NicsJsonFormat: Format[RequestSchemaAPI1638Class2Nics] = Json.format[RequestSchemaAPI1638Class2Nics]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright 2024 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.connector.api_1638

import play.api.libs.json._

/** Represents the Swagger definition for requestSchemaAPI1638_taxAvoidance_inner.
*/
case class RequestSchemaAPI1638TaxAvoidanceInner(
srn: String,
taxYear: String
)

object RequestSchemaAPI1638TaxAvoidanceInner {
implicit lazy val requestSchemaAPI1638TaxAvoidanceInnerJsonFormat: Format[RequestSchemaAPI1638TaxAvoidanceInner] =
Json.format[RequestSchemaAPI1638TaxAvoidanceInner]
}
32 changes: 32 additions & 0 deletions app/models/connector/api_1639/SuccessResponseAPI1639.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright 2024 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.connector.api_1639

import play.api.libs.json._

/** Represents the Swagger definition for successResponseAPI1639.
*/
case class SuccessResponseAPI1639(
taxAvoidance: Option[List[SuccessResponseAPI1639TaxAvoidanceInner]],
class2Nics: Option[SuccessResponseAPI1639Class2Nics]
)

object SuccessResponseAPI1639 {
implicit lazy val successResponseAPI1639JsonFormat: Format[SuccessResponseAPI1639] = Json.format[SuccessResponseAPI1639]

def empty: SuccessResponseAPI1639 = SuccessResponseAPI1639(None, None)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright 2024 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.connector.api_1639

import play.api.libs.json._

/** Voluntary contributions.
*/
case class SuccessResponseAPI1639Class2Nics(
class2VoluntaryContributions: Option[Boolean]
)

object SuccessResponseAPI1639Class2Nics {
implicit lazy val successResponseAPI1639Class2NicsJsonFormat: Format[SuccessResponseAPI1639Class2Nics] =
Json.format[SuccessResponseAPI1639Class2Nics]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright 2024 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.connector.api_1639

import play.api.libs.json._

/** Represents the Swagger definition for successResponseAPI1639_taxAvoidance_inner.
*/
case class SuccessResponseAPI1639TaxAvoidanceInner(
srn: String,
taxYear: String
)

object SuccessResponseAPI1639TaxAvoidanceInner {
implicit lazy val successResponseAPI1639TaxAvoidanceInnerJsonFormat: Format[SuccessResponseAPI1639TaxAvoidanceInner] =
Json.format[SuccessResponseAPI1639TaxAvoidanceInner]
}
Loading

0 comments on commit 303c55d

Please sign in to comment.