diff --git a/app/connectors/ConstructionIndustrySchemeConnector.scala b/app/connectors/ConstructionIndustrySchemeConnector.scala index b2040c8f..74960b28 100644 --- a/app/connectors/ConstructionIndustrySchemeConnector.scala +++ b/app/connectors/ConstructionIndustrySchemeConnector.scala @@ -16,6 +16,7 @@ package connectors +import models.amend.CreateAmendedMonthlyReturnRequest import models.monthlyreturns.* import models.requests.{GetMonthlyReturnForEditRequest, SendSuccessEmailRequest} import models.submission.* @@ -234,4 +235,16 @@ class ConstructionIndustrySchemeConnector @Inject() (config: ServicesConfig, htt } } + def createAmendedMonthlyReturn(request: CreateAmendedMonthlyReturnRequest)(implicit hc: HeaderCarrier): Future[Unit] = + http + .post(url"$cisBaseUrl/amend-monthly-return/create") + .withBody(Json.toJson(request)) + .execute[HttpResponse] + .flatMap { response => + response.status match { + case CREATED => Future.unit + case status => Future.failed(UpstreamErrorResponse(response.body, status, status)) + } + } + } diff --git a/app/controllers/amend/ConfirmAmendmentController.scala b/app/controllers/amend/ConfirmAmendmentController.scala index 740caf36..da4d8a23 100644 --- a/app/controllers/amend/ConfirmAmendmentController.scala +++ b/app/controllers/amend/ConfirmAmendmentController.scala @@ -17,38 +17,96 @@ package controllers.amend import controllers.actions.* -import pages.amend.ConfirmAmendmentPage +import models.UserAnswers +import models.amend.{AmendmentDetails, CreateAmendedMonthlyReturnRequest} +import models.monthlyreturns.ContinueReturnJourneyQueryParams +import pages.amend.{AmendmentDetailsPage, ConfirmAmendmentPage} +import pages.monthlyreturns.CisIdPage +import play.api.Logging import play.api.i18n.{I18nSupport, MessagesApi} import play.api.mvc.{Action, AnyContent, MessagesControllerComponents} import repositories.SessionRepository +import services.AmendMonthlyReturnService +import uk.gov.hmrc.http.HeaderCarrier import uk.gov.hmrc.play.bootstrap.frontend.controller.FrontendBaseController +import uk.gov.hmrc.play.http.HeaderCarrierConverter import views.html.amend.ConfirmAmendmentView import javax.inject.Inject -import scala.concurrent.ExecutionContext +import scala.concurrent.{ExecutionContext, Future} class ConfirmAmendmentController @Inject() ( override val messagesApi: MessagesApi, identify: IdentifierAction, getData: DataRetrievalAction, - requireData: DataRequiredAction, sessionRepository: SessionRepository, + amendMonthlyReturnService: AmendMonthlyReturnService, val controllerComponents: MessagesControllerComponents, view: ConfirmAmendmentView )(implicit ec: ExecutionContext) extends FrontendBaseController - with I18nSupport { + with I18nSupport + with Logging { - def onPageLoad: Action[AnyContent] = (identify andThen getData andThen requireData) { implicit request => - Ok(view()) + def onPageLoad(queryParams: ContinueReturnJourneyQueryParams): Action[AnyContent] = identify.async { + implicit request => + val amendmentDetails = AmendmentDetails( + instanceId = queryParams.instanceId, + taxYear = queryParams.taxYear, + taxMonth = queryParams.taxMonth + ) + + val updatedUserAnswers = + UserAnswers(request.userId) + .set(CisIdPage, queryParams.instanceId) + .flatMap(_.set(AmendmentDetailsPage, amendmentDetails)) + .get + + sessionRepository.set(updatedUserAnswers).map { _ => + Ok(view()) + } } def onSubmit: Action[AnyContent] = - (identify andThen getData andThen requireData).async { implicit request => - val updatedAnswers = request.userAnswers.set(ConfirmAmendmentPage, true).get + (identify andThen getData).async { implicit request => + request.userAnswers.flatMap(_.get(AmendmentDetailsPage)) match { + case Some(amendmentDetails) => + implicit val hc: HeaderCarrier = HeaderCarrierConverter.fromRequestAndSession(request, request.session) + + val createRequest = CreateAmendedMonthlyReturnRequest( + instanceId = amendmentDetails.instanceId, + taxYear = amendmentDetails.taxYear, + taxMonth = amendmentDetails.taxMonth, + version = 0 + ) + + ( + for { + _ <- amendMonthlyReturnService.createAmendedMonthlyReturn(createRequest) + updatedAnswers = request.userAnswers.get.set(ConfirmAmendmentPage, true).get + _ <- sessionRepository.set(updatedAnswers) + } yield Redirect( + controllers.amend.routes.ConfirmAmendmentController.onPageLoad( + ContinueReturnJourneyQueryParams( + instanceId = amendmentDetails.instanceId, + taxYear = amendmentDetails.taxYear, + taxMonth = amendmentDetails.taxMonth + ) + ) + ) // TODO: DTR-4657 + ).recover { case ex => + logger.warn( + s"[ConfirmAmendmentController] Failed to create amended monthly return for instanceId ${amendmentDetails.instanceId}", + ex + ) + Redirect(controllers.routes.JourneyRecoveryController.onPageLoad()) + } - sessionRepository.set(updatedAnswers).map { _ => - Redirect(controllers.amend.routes.ConfirmAmendmentController.onPageLoad()) + case None => + logger.warn( + s"[ConfirmAmendmentController] AmendmentDetails missing from userAnswers}" + ) + Future.successful(Redirect(controllers.routes.JourneyRecoveryController.onPageLoad())) } } } diff --git a/app/models/amend/AmendmentDetails.scala b/app/models/amend/AmendmentDetails.scala new file mode 100644 index 00000000..23687a76 --- /dev/null +++ b/app/models/amend/AmendmentDetails.scala @@ -0,0 +1,29 @@ +/* + * Copyright 2026 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.amend + +import play.api.libs.json.{Json, OFormat} + +case class AmendmentDetails( + instanceId: String, + taxYear: Int, + taxMonth: Int +) + +object AmendmentDetails { + given format: OFormat[AmendmentDetails] = Json.format[AmendmentDetails] +} diff --git a/app/models/amend/CreateAmendedMonthlyReturnRequest.scala b/app/models/amend/CreateAmendedMonthlyReturnRequest.scala new file mode 100644 index 00000000..3bfb4aa2 --- /dev/null +++ b/app/models/amend/CreateAmendedMonthlyReturnRequest.scala @@ -0,0 +1,30 @@ +/* + * Copyright 2026 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.amend + +import play.api.libs.json.{Json, OFormat} + +case class CreateAmendedMonthlyReturnRequest( + instanceId: String, + taxYear: Int, + taxMonth: Int, + version: Int +) + +object CreateAmendedMonthlyReturnRequest { + given format: OFormat[CreateAmendedMonthlyReturnRequest] = Json.format[CreateAmendedMonthlyReturnRequest] +} diff --git a/app/pages/amend/AmendmentDetailsPage.scala b/app/pages/amend/AmendmentDetailsPage.scala new file mode 100644 index 00000000..718c4e99 --- /dev/null +++ b/app/pages/amend/AmendmentDetailsPage.scala @@ -0,0 +1,29 @@ +/* + * Copyright 2026 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 pages.amend + +import models.amend.AmendmentDetails +import pages.QuestionPage +import play.api.libs.json.JsPath + +case object AmendmentDetailsPage extends QuestionPage[AmendmentDetails] { + + override def path: JsPath = JsPath \ toString + + override def toString: String = "amendmentDetails" + +} diff --git a/app/services/AmendMonthlyReturnService.scala b/app/services/AmendMonthlyReturnService.scala new file mode 100644 index 00000000..f9e0c5cd --- /dev/null +++ b/app/services/AmendMonthlyReturnService.scala @@ -0,0 +1,32 @@ +/* + * Copyright 2026 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 services + +import connectors.ConstructionIndustrySchemeConnector +import models.amend.CreateAmendedMonthlyReturnRequest +import uk.gov.hmrc.http.HeaderCarrier + +import javax.inject.{Inject, Singleton} +import scala.concurrent.Future + +@Singleton +class AmendMonthlyReturnService @Inject() (cisConnector: ConstructionIndustrySchemeConnector) { + + def createAmendedMonthlyReturn(request: CreateAmendedMonthlyReturnRequest)(implicit hc: HeaderCarrier): Future[Unit] = + cisConnector.createAmendedMonthlyReturn(request) + +} diff --git a/conf/app.routes b/conf/app.routes index 407a46f4..1f6960fb 100644 --- a/conf/app.routes +++ b/conf/app.routes @@ -171,8 +171,8 @@ POST /monthly-return/cancel-amended-monthly-return GET /amend-monthly-return/what-do-you-want-to-amend-nil controllers.amend.WhatDoYouWantToAmendNilController.onPageLoad() POST /amend-monthly-return/what-do-you-want-to-amend-nil controllers.amend.WhatDoYouWantToAmendNilController.onSubmit() -GET /manage-cis-return/amend-monthly-return/confirm-amendment controllers.amend.ConfirmAmendmentController.onPageLoad() -POST /manage-cis-return/amend-monthly-return/confirm-amendment controllers.amend.ConfirmAmendmentController.onSubmit() +GET /manage-cis-return/amend-monthly-return/confirm-amendments controllers.amend.ConfirmAmendmentController.onPageLoad(queryParams: models.monthlyreturns.ContinueReturnJourneyQueryParams) +POST /manage-cis-return/amend-monthly-return/confirm-amendments controllers.amend.ConfirmAmendmentController.onSubmit() GET /amend-monthly-return/what-do-you-want-to-amend-standard controllers.amend.WhatDoYouWantToAmendStandardController.onPageLoad() POST /amend-monthly-return/what-do-you-want-to-amend-standard controllers.amend.WhatDoYouWantToAmendStandardController.onSubmit() diff --git a/it/test/connectors/ConstructionIndustrySchemeConnectorSpec.scala b/it/test/connectors/ConstructionIndustrySchemeConnectorSpec.scala index 1e99d658..dfc729ea 100644 --- a/it/test/connectors/ConstructionIndustrySchemeConnectorSpec.scala +++ b/it/test/connectors/ConstructionIndustrySchemeConnectorSpec.scala @@ -19,6 +19,7 @@ package connectors import com.github.tomakehurst.wiremock.client.WireMock.* import itutil.ApplicationWithWiremock import models.ReturnType.MonthlyNilReturn +import models.amend.CreateAmendedMonthlyReturnRequest import models.requests.SendSuccessEmailRequest import models.monthlyreturns.* import models.submission.{ChrisSubmissionRequest, CreateSubmissionRequest, UpdateSubmissionRequest} @@ -989,4 +990,44 @@ class ConstructionIndustrySchemeConnectorSpec extends AnyWordSpec ex.asInstanceOf[UpstreamErrorResponse].statusCode mustBe INTERNAL_SERVER_ERROR } } + + "createAmendedMonthlyReturn(payload)" should { + + "POST /cis/amend-monthly-return/create and return Unit on 201" in { + val req = CreateAmendedMonthlyReturnRequest( + instanceId = cisId, + taxYear = 2025, + taxMonth = 1, + version = 0 + ) + + stubFor( + post(urlPathEqualTo("/cis/amend-monthly-return/create")) + .withHeader("Content-Type", equalTo("application/json")) + .withRequestBody(equalToJson(Json.toJson(req).toString(), true, true)) + .willReturn(aResponse().withStatus(CREATED)) + ) + + connector.createAmendedMonthlyReturn(req).futureValue mustBe ((): Unit) + } + + "fail the future when BE returns non-201 (e.g. 500)" in { + val req = CreateAmendedMonthlyReturnRequest( + instanceId = cisId, + taxYear = 2025, + taxMonth = 1, + version = 0 + ) + + stubFor( + post(urlPathEqualTo("/cis/amend-monthly-return/create")) + .willReturn(aResponse().withStatus(INTERNAL_SERVER_ERROR).withBody("boom")) + ) + + val ex = connector.createAmendedMonthlyReturn(req).failed.futureValue + + ex mustBe a[UpstreamErrorResponse] + ex.asInstanceOf[UpstreamErrorResponse].statusCode mustBe INTERNAL_SERVER_ERROR + } + } } diff --git a/test/controllers/amend/ConfirmAmendmentControllerSpec.scala b/test/controllers/amend/ConfirmAmendmentControllerSpec.scala index 481d7ab6..2676b369 100644 --- a/test/controllers/amend/ConfirmAmendmentControllerSpec.scala +++ b/test/controllers/amend/ConfirmAmendmentControllerSpec.scala @@ -17,29 +17,51 @@ package controllers.amend import base.SpecBase +import models.amend.AmendmentDetails +import models.monthlyreturns.ContinueReturnJourneyQueryParams import org.mockito.ArgumentMatchers.any import org.mockito.Mockito.when import org.scalatestplus.mockito.MockitoSugar import org.scalatestplus.mockito.MockitoSugar.mock +import pages.amend.AmendmentDetailsPage import play.api.inject.bind import play.api.test.FakeRequest import play.api.test.Helpers.* import repositories.SessionRepository +import services.AmendMonthlyReturnService import views.html.amend.ConfirmAmendmentView import scala.concurrent.Future class ConfirmAmendmentControllerSpec extends SpecBase { - val confirmAmendmentRoute: String = controllers.amend.routes.ConfirmAmendmentController.onSubmit().url + + private val queryParams = ContinueReturnJourneyQueryParams( + instanceId = "1234567890", + taxYear = 2025, + taxMonth = 1 + ) "ConfirmAmendment Controller" - { "must return OK and the correct view for a GET" in { + val mockSessionRepository = mock[SessionRepository] - val application = applicationBuilder(userAnswers = Some(emptyUserAnswers)).build() + when(mockSessionRepository.set(any())) thenReturn Future.successful(true) + + val application = + applicationBuilder(userAnswers = Some(emptyUserAnswers)) + .overrides( + bind[SessionRepository].toInstance(mockSessionRepository) + ) + .build() running(application) { - val request = FakeRequest(GET, controllers.amend.routes.ConfirmAmendmentController.onPageLoad().url) + val request = FakeRequest( + GET, + controllers.amend.routes.ConfirmAmendmentController + .onPageLoad(queryParams) + .url + ) val result = route(application, request).value @@ -50,28 +72,124 @@ class ConfirmAmendmentControllerSpec extends SpecBase { } } - "must redirect to the same page when onSubmit is true" in { + "must redirect to the same page when onSubmit succeeds" in { + val mockSessionRepository = mock[SessionRepository] + val mockAmendMonthlyReturnService = mock[AmendMonthlyReturnService] - val mockSessionRepository = mock[SessionRepository] + val amendmentDetails = AmendmentDetails( + instanceId = queryParams.instanceId, + taxYear = queryParams.taxYear, + taxMonth = queryParams.taxMonth + ) + + val userAnswers = + emptyUserAnswers + .set(AmendmentDetailsPage, amendmentDetails) + .success + .value when(mockSessionRepository.set(any())) thenReturn Future.successful(true) + when( + mockAmendMonthlyReturnService.createAmendedMonthlyReturn(any())(any()) + ) thenReturn Future.successful(()) + val application = - applicationBuilder(userAnswers = Some(emptyUserAnswers)) + applicationBuilder(userAnswers = Some(userAnswers)) .overrides( - bind[SessionRepository].toInstance(mockSessionRepository) + bind[SessionRepository].toInstance(mockSessionRepository), + bind[AmendMonthlyReturnService].toInstance(mockAmendMonthlyReturnService) ) .build() running(application) { val request = - FakeRequest(POST, confirmAmendmentRoute) - .withFormUrlEncodedBody() + FakeRequest( + POST, + controllers.amend.routes.ConfirmAmendmentController + .onSubmit() + .url + ).withFormUrlEncodedBody() val result = route(application, request).value status(result) mustEqual SEE_OTHER - redirectLocation(result).value mustEqual controllers.amend.routes.ConfirmAmendmentController.onPageLoad().url + + redirectLocation(result).value mustEqual + controllers.amend.routes.ConfirmAmendmentController + .onPageLoad(queryParams) + .url + } + } + + "must redirect to Journey Recovery when create amended monthly return fails" in { + val mockSessionRepository = mock[SessionRepository] + val mockAmendMonthlyReturnService = mock[AmendMonthlyReturnService] + + val amendmentDetails = AmendmentDetails( + instanceId = queryParams.instanceId, + taxYear = queryParams.taxYear, + taxMonth = queryParams.taxMonth + ) + + val userAnswers = + emptyUserAnswers + .set(AmendmentDetailsPage, amendmentDetails) + .success + .value + + when(mockSessionRepository.set(any())) thenReturn Future.successful(true) + + when( + mockAmendMonthlyReturnService.createAmendedMonthlyReturn(any())(any()) + ) thenReturn Future.failed(new RuntimeException("failed")) + + val application = + applicationBuilder(userAnswers = Some(userAnswers)) + .overrides( + bind[SessionRepository].toInstance(mockSessionRepository), + bind[AmendMonthlyReturnService].toInstance(mockAmendMonthlyReturnService) + ) + .build() + + running(application) { + val request = + FakeRequest( + POST, + controllers.amend.routes.ConfirmAmendmentController + .onSubmit() + .url + ).withFormUrlEncodedBody() + + val result = route(application, request).value + + status(result) mustEqual SEE_OTHER + + redirectLocation(result).value mustEqual + controllers.routes.JourneyRecoveryController.onPageLoad().url + } + } + + "must redirect to Journey Recovery when AmendmentDetails are missing from userAnswers" in { + val application = + applicationBuilder(userAnswers = Some(emptyUserAnswers)) + .build() + + running(application) { + val request = + FakeRequest( + POST, + controllers.amend.routes.ConfirmAmendmentController + .onSubmit() + .url + ).withFormUrlEncodedBody() + + val result = route(application, request).value + + status(result) mustEqual SEE_OTHER + + redirectLocation(result).value mustEqual + controllers.routes.JourneyRecoveryController.onPageLoad().url } } } diff --git a/test/controllers/amend/ConfirmCancelAmendmentYesNoControllerSpec.scala b/test/controllers/amend/ConfirmCancelAmendmentYesNoControllerSpec.scala index 1c750c94..dd806610 100644 --- a/test/controllers/amend/ConfirmCancelAmendmentYesNoControllerSpec.scala +++ b/test/controllers/amend/ConfirmCancelAmendmentYesNoControllerSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2026 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 controllers.amend import base.SpecBase diff --git a/test/controllers/monthlyreturns/CheckYourAnswersControllerSpec.scala b/test/controllers/monthlyreturns/CheckYourAnswersControllerSpec.scala index 2450f464..b22460b2 100644 --- a/test/controllers/monthlyreturns/CheckYourAnswersControllerSpec.scala +++ b/test/controllers/monthlyreturns/CheckYourAnswersControllerSpec.scala @@ -18,7 +18,6 @@ package controllers.monthlyreturns import base.SpecBase import models.monthlyreturns.Declaration.Confirmed -import models.monthlyreturns.UpdateMonthlyReturnRequest import models.{ReturnType, UserAnswers} import org.mockito.ArgumentMatchers.any import org.mockito.Mockito.* @@ -33,7 +32,6 @@ import viewmodels.checkAnswers.monthlyreturns.* import viewmodels.govuk.SummaryListFluency import views.html.monthlyreturns.CheckYourAnswersView import pages.submission.SubmissionJourneyCompletedPage -import uk.gov.hmrc.http.HeaderCarrier import java.time.LocalDate import scala.concurrent.Future diff --git a/test/forms/amend/ConfirmCancelAmendmentYesNoFormProviderSpec.scala b/test/forms/amend/ConfirmCancelAmendmentYesNoFormProviderSpec.scala index 4c8500d6..06311158 100644 --- a/test/forms/amend/ConfirmCancelAmendmentYesNoFormProviderSpec.scala +++ b/test/forms/amend/ConfirmCancelAmendmentYesNoFormProviderSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2026 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 forms.amend import forms.behaviours.BooleanFieldBehaviours diff --git a/test/models/amend/AmendmentDetailsSpec.scala b/test/models/amend/AmendmentDetailsSpec.scala new file mode 100644 index 00000000..4f5c0524 --- /dev/null +++ b/test/models/amend/AmendmentDetailsSpec.scala @@ -0,0 +1,36 @@ +/* + * Copyright 2026 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.amend + +import base.SpecBase +import play.api.libs.json.Json + +class AmendmentDetailsSpec extends SpecBase { + + "AmendmentDetails" - { + + "must round-trip JSON" in { + val model = AmendmentDetails( + instanceId = "1234567890", + taxYear = 2025, + taxMonth = 1 + ) + + Json.fromJson[AmendmentDetails](Json.toJson(model)).get mustBe model + } + } +} diff --git a/test/models/amend/CreateAmendedMonthlyReturnRequestSpec.scala b/test/models/amend/CreateAmendedMonthlyReturnRequestSpec.scala new file mode 100644 index 00000000..891b7b07 --- /dev/null +++ b/test/models/amend/CreateAmendedMonthlyReturnRequestSpec.scala @@ -0,0 +1,37 @@ +/* + * Copyright 2026 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.amend + +import base.SpecBase +import play.api.libs.json.Json + +class CreateAmendedMonthlyReturnRequestSpec extends SpecBase { + + "CreateAmendedMonthlyReturnRequest" - { + + "must round-trip JSON" in { + val model = CreateAmendedMonthlyReturnRequest( + instanceId = "1234567890", + taxYear = 2025, + taxMonth = 1, + version = 0 + ) + + Json.fromJson[CreateAmendedMonthlyReturnRequest](Json.toJson(model)).get mustBe model + } + } +} diff --git a/test/pages/amend/AmendmentDetailsPageSpec.scala b/test/pages/amend/AmendmentDetailsPageSpec.scala new file mode 100644 index 00000000..d28b06ed --- /dev/null +++ b/test/pages/amend/AmendmentDetailsPageSpec.scala @@ -0,0 +1,31 @@ +/* + * Copyright 2026 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 pages.amend + +import base.SpecBase +import play.api.libs.json.JsPath + +class AmendmentDetailsPageSpec extends SpecBase { + + "AmendmentDetailsPage" - { + + "must use amendmentDetails path" in { + AmendmentDetailsPage.path mustBe JsPath \ "amendmentDetails" + AmendmentDetailsPage.toString mustBe "amendmentDetails" + } + } +} diff --git a/test/services/AmendMonthlyReturnServiceSpec.scala b/test/services/AmendMonthlyReturnServiceSpec.scala new file mode 100644 index 00000000..e9390750 --- /dev/null +++ b/test/services/AmendMonthlyReturnServiceSpec.scala @@ -0,0 +1,58 @@ +/* + * Copyright 2026 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 services + +import base.SpecBase +import connectors.ConstructionIndustrySchemeConnector +import models.amend.CreateAmendedMonthlyReturnRequest +import org.mockito.Mockito.* +import org.mockito.ArgumentMatchers.any +import org.scalatestplus.mockito.MockitoSugar.mock +import uk.gov.hmrc.http.HeaderCarrier + +import scala.concurrent.Future + +class AmendMonthlyReturnServiceSpec extends SpecBase { + + "AmendMonthlyReturnService" - { + + "createAmendedMonthlyReturn should delegate to the CIS connector" in { + implicit val hc: HeaderCarrier = HeaderCarrier() + + val mockConnector = mock[ConstructionIndustrySchemeConnector] + + val request = CreateAmendedMonthlyReturnRequest( + instanceId = "1", + taxYear = 2025, + taxMonth = 1, + version = 0 + ) + + when( + mockConnector.createAmendedMonthlyReturn(any[CreateAmendedMonthlyReturnRequest]())( + any[HeaderCarrier]() + ) + ) thenReturn Future.successful(()) + + val service = new AmendMonthlyReturnService(mockConnector) + + service.createAmendedMonthlyReturn(request).futureValue mustBe ((): Unit) + + verify(mockConnector).createAmendedMonthlyReturn(request)(hc) + } + } +} diff --git a/test/views/amend/ConfirmCancelAmendmentYesNoViewSpec.scala b/test/views/amend/ConfirmCancelAmendmentYesNoViewSpec.scala index 876b167e..a797813a 100644 --- a/test/views/amend/ConfirmCancelAmendmentYesNoViewSpec.scala +++ b/test/views/amend/ConfirmCancelAmendmentYesNoViewSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2026 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 views.amend import base.SpecBase