Skip to content

Commit 3a6cc3e

Browse files
authored
APB-10760 new confirmation page with decision date (#209)
1 parent e741b99 commit 3a6cc3e

27 files changed

+281
-232
lines changed

app/uk/gov/hmrc/agentregistration/shared/AgentApplication.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ sealed trait AgentApplication:
3838
def linkId: LinkId
3939
def groupId: GroupId
4040
def createdAt: Instant
41+
def submittedAt: Option[Instant] // only populated when the application is submitted, not during the registration journey
4142
def applicationState: ApplicationState
4243
def businessType: BusinessType
4344
def userRole: Option[UserRole]
@@ -107,6 +108,8 @@ sealed trait AgentApplication:
107108
expectedDataNotDefinedError("numberOfIndividuals")
108109
)
109110

111+
def getSubmittedAt: Instant = submittedAt.getOrElse(expectedDataNotDefinedError("submittedAt"))
112+
110113
private def as[T <: AgentApplication](using ct: reflect.ClassTag[T]): Option[T] =
111114
this match
112115
case t: T => Some(t)
@@ -132,6 +135,7 @@ final case class AgentApplicationSoleTrader(
132135
override val linkId: LinkId,
133136
override val groupId: GroupId,
134137
override val createdAt: Instant,
138+
override val submittedAt: Option[Instant],
135139
override val applicationState: ApplicationState,
136140
override val userRole: Option[UserRole],
137141
businessDetails: Option[BusinessDetailsSoleTrader],
@@ -162,6 +166,7 @@ final case class AgentApplicationLlp(
162166
override val linkId: LinkId,
163167
override val groupId: GroupId,
164168
override val createdAt: Instant,
169+
override val submittedAt: Option[Instant],
165170
override val applicationState: ApplicationState,
166171
override val userRole: Option[UserRole],
167172
businessDetails: Option[BusinessDetailsLlp],
@@ -191,6 +196,7 @@ final case class AgentApplicationLimitedCompany(
191196
override val linkId: LinkId,
192197
override val groupId: GroupId,
193198
override val createdAt: Instant,
199+
override val submittedAt: Option[Instant],
194200
override val applicationState: ApplicationState,
195201
override val userRole: Option[UserRole],
196202
businessDetails: Option[BusinessDetailsLimitedCompany],
@@ -220,6 +226,7 @@ final case class AgentApplicationGeneralPartnership(
220226
override val linkId: LinkId,
221227
override val groupId: GroupId,
222228
override val createdAt: Instant,
229+
override val submittedAt: Option[Instant],
223230
override val applicationState: ApplicationState,
224231
override val userRole: Option[UserRole],
225232
businessDetails: Option[BusinessDetailsGeneralPartnership],
@@ -247,6 +254,7 @@ final case class AgentApplicationLimitedPartnership(
247254
override val linkId: LinkId,
248255
override val groupId: GroupId,
249256
override val createdAt: Instant,
257+
override val submittedAt: Option[Instant],
250258
override val applicationState: ApplicationState,
251259
override val userRole: Option[UserRole],
252260
businessDetails: Option[BusinessDetailsPartnership],
@@ -274,6 +282,7 @@ final case class AgentApplicationScottishLimitedPartnership(
274282
override val linkId: LinkId,
275283
override val groupId: GroupId,
276284
override val createdAt: Instant,
285+
override val submittedAt: Option[Instant],
277286
override val applicationState: ApplicationState,
278287
override val userRole: Option[UserRole],
279288
businessDetails: Option[BusinessDetailsPartnership],
@@ -301,6 +310,7 @@ final case class AgentApplicationScottishPartnership(
301310
override val linkId: LinkId,
302311
override val groupId: GroupId,
303312
override val createdAt: Instant,
313+
override val submittedAt: Option[Instant],
304314
override val applicationState: ApplicationState,
305315
override val userRole: Option[UserRole],
306316
businessDetails: Option[BusinessDetailsScottishPartnership],

app/uk/gov/hmrc/agentregistrationfrontend/config/AppConfig.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ class AppConfig @Inject() (
9999
val companiesHouseUrl: String = ConfigHelper.readConfigAsValidUrlString("urls.companies-house", configuration)
100100
val contacHmrctUrl: String = ConfigHelper.readConfigAsValidUrlString("urls.contact-hmrc", configuration)
101101

102+
val applicationDecisionLeadTime: FiniteDuration = configuration.get[FiniteDuration]("application-decision-lead-time")
103+
102104
object Upscan:
103105

104106
val maxFileSize: ConfigMemorySize = configuration.underlying.getMemorySize("uploads.max-file-size")

app/uk/gov/hmrc/agentregistrationfrontend/connectors/AgentRegistrationRiskingConnector.scala

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@
1616

1717
package uk.gov.hmrc.agentregistrationfrontend.connectors
1818

19-
import uk.gov.hmrc.agentregistrationfrontend.config.AppConfig
19+
import uk.gov.hmrc.agentregistration.shared.AgentApplicationId
2020
import uk.gov.hmrc.agentregistration.shared.risking.SubmitForRiskingRequest
21+
import uk.gov.hmrc.agentregistrationfrontend.config.AppConfig
22+
import uk.gov.hmrc.agentregistrationfrontend.model.ApplicationForRiskingStatus
2123
import uk.gov.hmrc.http.client.HttpClientV2
2224

2325
import javax.inject.Inject
@@ -54,4 +56,22 @@ extends Connector:
5456
)
5557
.andLogOnFailure(s"Failed to submit agent application for risking: ${submitForRiskingRequest.agentApplication.agentApplicationId.value}")
5658

59+
def getApplicationStatus(agentApplicationId: AgentApplicationId)(using RequestHeader): Future[ApplicationForRiskingStatus] =
60+
val url: URL = url"$baseUrl/application-status/${agentApplicationId.value}"
61+
httpClient
62+
.get(url)
63+
.execute[HttpResponse]
64+
.map: response =>
65+
response.status match
66+
case Status.OK => (response.json \ "status").as[ApplicationForRiskingStatus]
67+
case other =>
68+
Errors.throwUpstreamErrorResponse(
69+
httpMethod = "GET",
70+
url = url,
71+
status = other,
72+
response = response,
73+
info = "get application status problem"
74+
)
75+
.andLogOnFailure(s"Failed to get application status for agent application ID: ${agentApplicationId.value}")
76+
5777
private val baseUrl: String = appConfig.agentRegistrationRiskingBaseUrl + "/agent-registration-risking"

app/uk/gov/hmrc/agentregistrationfrontend/controllers/applicant/AgentApplicationController.scala

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,31 @@ import play.api.mvc.AnyContent
2121
import play.api.mvc.MessagesControllerComponents
2222
import uk.gov.hmrc.agentregistration.shared.AgentApplication
2323
import uk.gov.hmrc.agentregistrationfrontend.action.applicant.ApplicantActions
24+
import uk.gov.hmrc.agentregistrationfrontend.config.AppConfig
25+
import uk.gov.hmrc.agentregistrationfrontend.model.ApplicationForRiskingStatus
26+
import uk.gov.hmrc.agentregistrationfrontend.services.applicant.AgentRegistrationRiskingService
27+
import uk.gov.hmrc.agentregistrationfrontend.util.DisplayDate.displayDateForLang
2428
import uk.gov.hmrc.agentregistrationfrontend.views.html.SimplePage
2529
import uk.gov.hmrc.agentregistrationfrontend.views.html.applicant.ConfirmationPage
2630
import uk.gov.hmrc.agentregistrationfrontend.views.html.applicant.ViewApplicationPage
2731

32+
import java.time.Instant
33+
import java.time.LocalDate
34+
import java.time.ZoneId
35+
import java.time.temporal.ChronoUnit
2836
import javax.inject.Inject
2937
import javax.inject.Singleton
38+
import scala.concurrent.duration.FiniteDuration
3039

3140
@Singleton
3241
class AgentApplicationController @Inject() (
3342
actions: ApplicantActions,
3443
mcc: MessagesControllerComponents,
3544
simplePage: SimplePage,
3645
confirmationPage: ConfirmationPage,
37-
viewApplicationPage: ViewApplicationPage
46+
viewApplicationPage: ViewApplicationPage,
47+
appConfig: AppConfig,
48+
agentRegistrationRiskingService: AgentRegistrationRiskingService
3849
)
3950
extends FrontendController(mcc, actions):
4051

@@ -59,11 +70,36 @@ extends FrontendController(mcc, actions):
5970

6071
def applicationSubmitted: Action[AnyContent] = actions
6172
.getApplicationSubmitted
62-
.getBusinessPartnerRecord:
73+
.async:
6374
implicit request =>
64-
Ok(confirmationPage(
65-
entityName = request.businessPartnerRecordResponse.getEntityName,
66-
agentApplication = request.get[AgentApplication]
75+
val agentApplication: AgentApplication = request.get
76+
// make a call to risking for the latest status of the application
77+
agentRegistrationRiskingService
78+
.getApplicationStatus(agentApplication.agentApplicationId)
79+
.map:
80+
case ApplicationForRiskingStatus.ReadyForSubmission => // show the confirmation screen
81+
val decisionLeadTime: FiniteDuration = appConfig.applicationDecisionLeadTime
82+
val submittedAt: Instant = agentApplication.getSubmittedAt
83+
val localDateOfDecision: LocalDate =
84+
submittedAt
85+
.plus(decisionLeadTime.toMillis, ChronoUnit.MILLIS)
86+
.atZone(ZoneId.systemDefault())
87+
.toLocalDate
88+
Ok(confirmationPage(
89+
dateOfDecision = displayDateForLang(Some(localDateOfDecision)),
90+
agentApplication = agentApplication
91+
))
92+
case _ => Redirect(AppRoutes.apply.AgentApplicationController.viewApplicationProgress)
93+
94+
def viewApplicationProgress: Action[AnyContent] = actions
95+
.getApplicationSubmitted:
96+
implicit request =>
97+
val agentApplication: AgentApplication = request.get
98+
Ok(simplePage(
99+
h1 = s"Application reference: ${agentApplication.agentApplicationId.value}",
100+
bodyText = Some(
101+
"Placeholder for the Application Progress page..."
102+
)
67103
))
68104

69105
def viewSubmittedApplication: Action[AnyContent] = actions

app/uk/gov/hmrc/agentregistrationfrontend/controllers/applicant/DeclarationController.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,14 @@ import uk.gov.hmrc.agentregistrationfrontend.services.applicant.AgentRegistratio
3131
import uk.gov.hmrc.agentregistrationfrontend.services.individual.IndividualProvideDetailsService
3232
import uk.gov.hmrc.agentregistrationfrontend.views.html.applicant.DeclarationPage
3333

34+
import java.time.Clock
35+
import java.time.Instant
3436
import javax.inject.Inject
3537
import javax.inject.Singleton
3638

3739
@Singleton
3840
class DeclarationController @Inject() (
41+
clock: Clock,
3942
mcc: MessagesControllerComponents,
4043
actions: ApplicantActions,
4144
view: DeclarationPage,
@@ -91,5 +94,7 @@ extends FrontendController(mcc, actions):
9194
request.agentApplication
9295
.modify(_.applicationState)
9396
.setTo(ApplicationState.SentForRisking)
97+
.modify(_.submittedAt)
98+
.setTo(Some(Instant.now(clock)))
9499
)
95100
yield Redirect(AppRoutes.apply.AgentApplicationController.applicationSubmitted)

app/uk/gov/hmrc/agentregistrationfrontend/controllers/applicant/TaskListController.scala

Lines changed: 2 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,12 @@ import play.api.mvc.AnyContent
2121
import play.api.mvc.MessagesControllerComponents
2222
import uk.gov.hmrc.agentregistration.shared.AgentApplication
2323
import uk.gov.hmrc.agentregistration.shared.BusinessPartnerRecordResponse
24-
import uk.gov.hmrc.agentregistration.shared.StateOfAgreement
2524
import uk.gov.hmrc.agentregistration.shared.hasCheckPassed
2625
import uk.gov.hmrc.agentregistration.shared.individual.IndividualProvidedDetails
27-
import uk.gov.hmrc.agentregistration.shared.individual.ProvidedDetailsState
28-
import uk.gov.hmrc.agentregistration.shared.lists.NumberOfIndividuals
29-
import uk.gov.hmrc.agentregistration.shared.util.SafeEquals.*
3026
import uk.gov.hmrc.agentregistrationfrontend.action.applicant.ApplicantActions
31-
import uk.gov.hmrc.agentregistrationfrontend.model.TaskListStatus
32-
import uk.gov.hmrc.agentregistrationfrontend.model.TaskStatus
33-
import uk.gov.hmrc.agentregistrationfrontend.views.html.applicant.TaskListPage
27+
import uk.gov.hmrc.agentregistrationfrontend.model.taskListStatus
3428
import uk.gov.hmrc.agentregistrationfrontend.services.individual.IndividualProvideDetailsService
29+
import uk.gov.hmrc.agentregistrationfrontend.views.html.applicant.TaskListPage
3530

3631
import javax.inject.Inject
3732
import javax.inject.Singleton
@@ -74,70 +69,3 @@ extends FrontendController(mcc, actions):
7469
entityName = request.get[BusinessPartnerRecordResponse].getEntityName,
7570
agentApplication = agentApplication
7671
))
77-
78-
extension (agentApplication: AgentApplication)
79-
80-
def taskListStatus(existingList: List[IndividualProvidedDetails]): TaskListStatus = {
81-
val contactIsComplete = agentApplication.applicantContactDetails.exists(_.isComplete)
82-
val amlsDetailsCompleted = agentApplication.amlsDetails.exists(_.isComplete)
83-
val agentDetailsIsComplete = agentApplication.agentDetails.exists(_.isComplete)
84-
val hmrcStandardForAgentsAgreed = agentApplication.hmrcStandardForAgentsAgreed === StateOfAgreement.Agreed
85-
def otherRelevantIndividualsComplete(existingList: List[IndividualProvidedDetails]): Boolean =
86-
agentApplication.hasOtherRelevantIndividuals match
87-
case Some(true) => existingList.exists(!_.isPersonOfControl)
88-
case Some(false) => true
89-
case None => false
90-
def listDetailsCompleted(existingList: List[IndividualProvidedDetails]): Boolean =
91-
agentApplication match
92-
case a: AgentApplication.IsAgentApplicationForDeclaringNumberOfKeyIndividuals =>
93-
NumberOfIndividuals.isKeyIndividualListComplete(existingList.count(_.isPersonOfControl), a.numberOfIndividuals)
94-
&& otherRelevantIndividualsComplete(existingList)
95-
case a: AgentApplication.IsIncorporated =>
96-
NumberOfIndividuals.isKeyIndividualListComplete(existingList.count(_.isPersonOfControl), a.numberOfIndividuals)
97-
&& otherRelevantIndividualsComplete(existingList)
98-
case _ => false
99-
100-
val listProgressComplete = listDetailsCompleted(existingList) && existingList.forall(_.hasFinished)
101-
// any state other than Precreated indicates the link has been sent; require the list to be non-empty
102-
val listSharingComplete =
103-
listDetailsCompleted(existingList) &&
104-
existingList.forall(_.providedDetailsState =!= ProvidedDetailsState.Precreated)
105-
TaskListStatus(
106-
contactDetails = TaskStatus(
107-
canStart = true, // Contact details can be started at any time
108-
isComplete = contactIsComplete
109-
),
110-
amlsDetails = TaskStatus(
111-
canStart = true, // AMLS details can be started at any time
112-
isComplete = amlsDetailsCompleted
113-
),
114-
agentDetails = TaskStatus(
115-
canStart = contactIsComplete, // Agent details can be started only when contact details are complete
116-
isComplete = agentDetailsIsComplete
117-
),
118-
hmrcStandardForAgents = TaskStatus(
119-
canStart = true, // HMRC Standard for Agents can be started at any time
120-
isComplete = hmrcStandardForAgentsAgreed
121-
),
122-
listDetails = TaskStatus(
123-
canStart = contactIsComplete, // List details can be started only once we have a contact name
124-
isComplete = listDetailsCompleted(existingList)
125-
),
126-
listShare = TaskStatus(
127-
canStart = listDetailsCompleted(existingList), // List sharing cannot be started until list details are completed
128-
isComplete = listSharingComplete
129-
),
130-
listTracking = TaskStatus(
131-
canStart = listSharingComplete, // List tracking cannot be started until list share is complete
132-
isComplete = listProgressComplete
133-
),
134-
declaration = TaskStatus(
135-
canStart =
136-
contactIsComplete
137-
&& amlsDetailsCompleted
138-
&& agentDetailsIsComplete
139-
&& hmrcStandardForAgentsAgreed, // Declaration can be started only when all prior tasks are complete
140-
isComplete = false // Declaration is never "complete" until submission
141-
)
142-
)
143-
}

app/uk/gov/hmrc/agentregistrationfrontend/model/AgentApplicationExt.scala

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@
1616

1717
package uk.gov.hmrc.agentregistrationfrontend.model
1818

19+
import uk.gov.hmrc.agentregistration.shared.*
1920
import uk.gov.hmrc.agentregistration.shared.individual.IndividualProvidedDetails
2021
import uk.gov.hmrc.agentregistration.shared.individual.ProvidedDetailsState
21-
import uk.gov.hmrc.agentregistration.shared.lists.NumberOfRequiredKeyIndividuals
22+
import uk.gov.hmrc.agentregistration.shared.lists.NumberOfIndividuals
2223
import uk.gov.hmrc.agentregistration.shared.util.SafeEquals.=!=
2324
import uk.gov.hmrc.agentregistration.shared.util.SafeEquals.===
24-
import uk.gov.hmrc.agentregistration.shared.*
2525

2626
extension (agentApplication: AgentApplication)
2727

@@ -40,11 +40,12 @@ extension (agentApplication: AgentApplication)
4040
def listDetailsCompleted(existingList: List[IndividualProvidedDetails]): Boolean =
4141
agentApplication match
4242
case a: AgentApplication.IsAgentApplicationForDeclaringNumberOfKeyIndividuals =>
43-
a.getNumberOfRequiredKeyIndividuals.exists(n =>
44-
NumberOfRequiredKeyIndividuals.isKeyIndividualListComplete(existingList.count(_.isPersonOfControl), n)
45-
)
43+
NumberOfIndividuals.isKeyIndividualListComplete(existingList.count(_.isPersonOfControl), a.numberOfIndividuals)
44+
&& otherRelevantIndividualsComplete(existingList)
45+
case a: AgentApplication.IsIncorporated =>
46+
NumberOfIndividuals.isKeyIndividualListComplete(existingList.count(_.isPersonOfControl), a.numberOfIndividuals)
4647
&& otherRelevantIndividualsComplete(existingList)
47-
case _ => true
48+
case _ => false
4849

4950
val listProgressComplete = listDetailsCompleted(existingList) && existingList.forall(_.hasFinished)
5051
// any state other than Precreated indicates the link has been sent; require the list to be non-empty
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright 2026 HM Revenue & Customs
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package uk.gov.hmrc.agentregistrationfrontend.model
18+
19+
import play.api.libs.json.Format
20+
import uk.gov.hmrc.agentregistration.shared.util.JsonFormatsFactory
21+
22+
enum ApplicationForRiskingStatus:
23+
24+
case ReadyForSubmission
25+
case SubmittedForRisking
26+
case Approved
27+
case FailedNonFixable
28+
case FailedFixable
29+
case ReadyForResubmission
30+
31+
object ApplicationForRiskingStatus:
32+
given Format[ApplicationForRiskingStatus] = JsonFormatsFactory.makeEnumFormat[ApplicationForRiskingStatus]

app/uk/gov/hmrc/agentregistrationfrontend/services/applicant/AgentRegistrationRiskingService.scala

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@
1717
package uk.gov.hmrc.agentregistrationfrontend.services.applicant
1818

1919
import play.api.mvc.RequestHeader
20-
import uk.gov.hmrc.agentregistrationfrontend.connectors.AgentRegistrationRiskingConnector
20+
import uk.gov.hmrc.agentregistration.shared.AgentApplicationId
2121
import uk.gov.hmrc.agentregistration.shared.risking.SubmitForRiskingRequest
22+
import uk.gov.hmrc.agentregistrationfrontend.connectors.AgentRegistrationRiskingConnector
23+
import uk.gov.hmrc.agentregistrationfrontend.model.ApplicationForRiskingStatus
2224
import uk.gov.hmrc.agentregistrationfrontend.util.RequestAwareLogging
2325

2426
import javax.inject.Inject
@@ -34,3 +36,7 @@ extends RequestAwareLogging:
3436

3537
def submitForRisking(submitForRiskingRequest: SubmitForRiskingRequest)(using request: RequestHeader): Future[Unit] = agentRegistrationRiskingConnector
3638
.submitForRisking(submitForRiskingRequest)
39+
40+
def getApplicationStatus(agentApplicationId: AgentApplicationId)(using request: RequestHeader): Future[ApplicationForRiskingStatus] =
41+
agentRegistrationRiskingConnector
42+
.getApplicationStatus(agentApplicationId)

0 commit comments

Comments
 (0)