Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion app/models/submission/ChrisPollResponse.scala
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ case class ChrisPollResponse(
intervalSeconds: Option[Int],
error: Option[JsValue],
irMarkReceived: Option[String],
lastMessageDate: Option[String]
lastMessageDate: Option[String],
acceptedTime: Option[String]
)

object ChrisPollResponse {
Expand Down
1 change: 1 addition & 0 deletions app/models/submission/ChrisSubmissionResponse.scala
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ final case class ChrisSubmissionResponse(
correlationId: Option[String] = None,
responseEndPoint: Option[ResponseEndPointDto] = None,
gatewayTimestamp: Option[String] = None,
acceptedTime: Option[String] = None,
error: Option[JsValue] = None
)

Expand Down
23 changes: 10 additions & 13 deletions app/services/submission/SubmissionService.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,8 @@ import uk.gov.hmrc.http.HeaderCarrier
import utils.DateTimeFormats
import utils.TypeUtils.*

import java.time.format.DateTimeFormatter
import java.time.{Instant, LocalDateTime, YearMonth}
import java.util.{Locale, TimeZone}
import java.util.Locale
import javax.inject.{Inject, Singleton}
import scala.concurrent.{ExecutionContext, Future}
import scala.util.{Success, Try}
Expand All @@ -51,13 +50,6 @@ class SubmissionService @Inject() (
)(implicit ec: ExecutionContext)
extends Logging {

private val dateFormatter =
DateTimeFormatter
.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS")
.withZone(TimeZone.getTimeZone("GMT").toZoneId)

// Orchestration

def create(ua: UserAnswers)(implicit hc: HeaderCarrier): Future[(CreateSubmissionResponse, UserAnswers)] =
for {
req <- buildCreateRequest(ua)
Expand Down Expand Up @@ -102,7 +94,7 @@ class SubmissionService @Inject() (
ua,
chrisResp.hmrcMarkGenerated,
chrisResp.status,
chrisResp.gatewayTimestamp,
chrisResp.acceptedTime,
None,
chrisResp.error
)
Expand All @@ -112,10 +104,15 @@ class SubmissionService @Inject() (
ua: UserAnswers,
hmrcMarkGenerated: String,
status: String,
gatewayTimestamp: Option[String],
acceptedTime: Option[String],
irMarkReceived: Option[String] = None,
error: Option[JsValue] = None
)(implicit req: DataRequest[AnyContent], hc: HeaderCarrier): Future[Unit] = {
val acceptedTimestamp = Option.when(status == "SUBMITTED" || status == "SUBMITTED_NO_RECEIPT") {
acceptedTime
.flatMap(t => Try(LocalDateTime.parse(t)).toOption)
.getOrElse(LocalDateTime.now())
}

val instanceId = ua.get(CisIdPage).getOrElse(throw new RuntimeException("CIS ID missing"))
val ym = selectedYearMonth(ua)
Expand All @@ -130,7 +127,7 @@ class SubmissionService @Inject() (
taxYear = ym.getYear,
taxMonth = ym.getMonthValue,
submittableStatus = status,
acceptedTime = gatewayTimestamp,
acceptedTime = acceptedTimestamp.map(_.toString),
submissionRequestDate = Some(LocalDateTime.now()),
govtalkErrorCode = error.flatMap(js => (js \ "number").asOpt[String]),
govtalkErrorType = error.flatMap(js => (js \ "type").asOpt[String]),
Expand Down Expand Up @@ -214,7 +211,7 @@ class SubmissionService @Inject() (
userAnswers,
submissionDetails.irMark,
result.status,
Some(dateFormatter.format(submissionDetails.submittedAt)),
result.acceptedTime,
result.irMarkReceived,
result.error
)
Expand Down
12 changes: 8 additions & 4 deletions test/models/submission/ChrisPollResponseSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ class ChrisPollResponseSpec extends AnyWordSpec with Matchers {
| "intervalSeconds": 1,
| "error": { "number": "5005", "type": "fatal", "text": "Boom" },
| "irMarkReceived": "2342345asdfasdgf",
| "lastMessageDate": "2026-03-20T10:15:30Z"
| "lastMessageDate": "2026-03-20T10:15:30Z",
| "acceptedTime": "2026-03-20T10:15:30"
|}
""".stripMargin
)
Expand All @@ -45,7 +46,8 @@ class ChrisPollResponseSpec extends AnyWordSpec with Matchers {
Some(1),
Some(JsObject(Seq("number" -> JsString("5005"), "type" -> JsString("fatal"), "text" -> JsString("Boom")))),
Some("2342345asdfasdgf"),
Some("2026-03-20T10:15:30Z")
Some("2026-03-20T10:15:30Z"),
Some("2026-03-20T10:15:30")
)
)
}
Expand Down Expand Up @@ -75,6 +77,7 @@ class ChrisPollResponseSpec extends AnyWordSpec with Matchers {
Some(1),
Some(JsObject(Seq("number" -> JsString("5005"), "type" -> JsString("fatal"), "text" -> JsString("Boom")))),
Some("2342345asdfasdgf"),
Some("2026-03-20T10:15:30Z"),
Some("2026-03-20T10:15:30Z")
)
val js = Json.toJson(model)
Expand All @@ -90,7 +93,7 @@ class ChrisPollResponseSpec extends AnyWordSpec with Matchers {
}

"write to expected JSON when pollUrl is None" in {
val model = ChrisPollResponse("SUBMITTED", None, None, None, None, None)
val model = ChrisPollResponse("SUBMITTED", None, None, None, None, None, None)
val js = Json.toJson(model)

(js \ "status").as[String] mustBe "SUBMITTED"
Expand All @@ -108,6 +111,7 @@ class ChrisPollResponseSpec extends AnyWordSpec with Matchers {
Some(1),
Some(JsObject(Seq("number" -> JsString("5005"), "type" -> JsString("fatal"), "text" -> JsString("Boom")))),
Some("2342345asdfasdgf"),
Some("2026-03-20T10:15:30Z"),
Some("2026-03-20T10:15:30Z")
)

Expand All @@ -118,7 +122,7 @@ class ChrisPollResponseSpec extends AnyWordSpec with Matchers {
}

"round-trip (write then read) preserves values without pollUrl" in {
val model = ChrisPollResponse("ACCEPTED", None, None, None, None, None)
val model = ChrisPollResponse("ACCEPTED", None, None, None, None, None, None)

val js = Json.toJson(model)
val out = js.as[ChrisPollResponse]
Expand Down
26 changes: 16 additions & 10 deletions test/services/submission/SubmissionServiceSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,8 @@ class SubmissionServiceSpec extends SpecBase with TryValues {
val chrisResp = mkChrisResp(
status = "DEPARTMENTAL_ERROR",
ts = "2025-02-02T10:20:30",
err = Some(Json.obj("number" -> "123", "type" -> "business", "text" -> "oops"))
err = Some(Json.obj("number" -> "123", "type" -> "business", "text" -> "oops")),
accepted = Some("2025-02-02T10:20:30")
)

service.updateSubmissionFromChrisResponse("sub-123", ua, chrisResp).futureValue
Expand All @@ -481,7 +482,7 @@ class SubmissionServiceSpec extends SpecBase with TryValues {
upd.taxMonth mustBe 10
upd.hmrcMarkGenerated mustBe Some("Dj5TVJDyRYCn9zta5EdySeY4fyA=")
upd.submittableStatus mustBe "DEPARTMENTAL_ERROR"
upd.acceptedTime mustBe Some("2025-02-02T10:20:30")
upd.acceptedTime mustBe None
upd.emailRecipient mustBe Some("test@test.com")
upd.govtalkErrorCode mustBe Some("123")
upd.govtalkErrorType mustBe Some("business")
Expand Down Expand Up @@ -611,7 +612,7 @@ class SubmissionServiceSpec extends SpecBase with TryValues {
.value

when(connector.getSubmissionStatus(any, any[String])(any[HeaderCarrier]))
.thenReturn(Future.successful(ChrisPollResponse("SUBMITTED", Some("someUrl"), None, None, None, None)))
.thenReturn(Future.successful(ChrisPollResponse("SUBMITTED", Some("someUrl"), None, None, None, None, None)))
when(sessionRepository.set(any[UserAnswers]))
.thenReturn(Future.successful(true))

Expand Down Expand Up @@ -686,7 +687,7 @@ class SubmissionServiceSpec extends SpecBase with TryValues {
.value

when(connector.getSubmissionStatus(any, any[String])(any[HeaderCarrier]))
.thenReturn(Future.successful(ChrisPollResponse("ACCEPTED", Some("someUrl"), None, None, None, None)))
.thenReturn(Future.successful(ChrisPollResponse("ACCEPTED", Some("someUrl"), None, None, None, None, None)))
when(sessionRepository.set(any[UserAnswers]))
.thenReturn(Future.successful(true))
when(connector.updateSubmission(any[String], any[UpdateSubmissionRequest])(any[HeaderCarrier]))
Expand Down Expand Up @@ -715,7 +716,7 @@ class SubmissionServiceSpec extends SpecBase with TryValues {
val ua = uaBase

when(connector.getSubmissionStatus(any, any)(any))
.thenReturn(Future.successful(ChrisPollResponse("SUBMITTED", Some("someUrl"), None, None, None, None)))
.thenReturn(Future.successful(ChrisPollResponse("SUBMITTED", Some("someUrl"), None, None, None, None, None)))

val result = service.checkAndUpdateSubmissionStatus(ua).failed.futureValue

Expand Down Expand Up @@ -803,6 +804,7 @@ class SubmissionServiceSpec extends SpecBase with TryValues {
JsObject(Seq("number" -> JsString("5005"), "type" -> JsString("fatal"), "text" -> JsString("Boom")))
),
Some("2342345asdfasdgf"),
Some("2025-01-01T00:00:30Z"),
Some("2025-01-01T00:00:30Z")
)
)
Expand Down Expand Up @@ -863,7 +865,9 @@ class SubmissionServiceSpec extends SpecBase with TryValues {
.value

when(connector.getSubmissionStatus(any, any[String])(any[HeaderCarrier]))
.thenReturn(Future.successful(ChrisPollResponse("PENDING", Some("newPollUrl"), Some(30), None, None, None)))
.thenReturn(
Future.successful(ChrisPollResponse("PENDING", Some("newPollUrl"), Some(30), None, None, None, None))
)
when(connector.updateSubmission(any[String], any[UpdateSubmissionRequest])(any[HeaderCarrier]))
.thenReturn(Future.unit)
when(sessionRepository.set(any[UserAnswers]))
Expand Down Expand Up @@ -921,7 +925,7 @@ class SubmissionServiceSpec extends SpecBase with TryValues {
.value

when(connector.getSubmissionStatus(any, any[String])(any[HeaderCarrier]))
.thenReturn(Future.successful(ChrisPollResponse("SUBMITTED", Some("newUrl"), Some(10), None, None, None)))
.thenReturn(Future.successful(ChrisPollResponse("SUBMITTED", Some("newUrl"), Some(10), None, None, None, None)))
when(connector.updateSubmission(any[String], any[UpdateSubmissionRequest])(any[HeaderCarrier]))
.thenReturn(Future.unit)
when(sessionRepository.set(any[UserAnswers]))
Expand Down Expand Up @@ -972,7 +976,7 @@ class SubmissionServiceSpec extends SpecBase with TryValues {
.value

when(connector.getSubmissionStatus(any, any[String])(any[HeaderCarrier]))
.thenReturn(Future.successful(ChrisPollResponse("PENDING", Some("someurl"), None, None, None, None)))
.thenReturn(Future.successful(ChrisPollResponse("PENDING", Some("someurl"), None, None, None, None, None)))
when(connector.updateSubmission(any[String], any[UpdateSubmissionRequest])(any[HeaderCarrier]))
.thenReturn(Future.unit)

Expand Down Expand Up @@ -1025,7 +1029,7 @@ class SubmissionServiceSpec extends SpecBase with TryValues {
.value

when(connector.getSubmissionStatus(any, any[String])(any[HeaderCarrier]))
.thenReturn(Future.successful(ChrisPollResponse("ACCEPTED", Some("someurl"), None, None, None, None)))
.thenReturn(Future.successful(ChrisPollResponse("ACCEPTED", Some("someurl"), None, None, None, None, None)))
when(connector.updateSubmission(any[String], any[UpdateSubmissionRequest])(any[HeaderCarrier]))
.thenReturn(Future.unit)

Expand Down Expand Up @@ -1564,7 +1568,8 @@ class SubmissionServiceSpec extends SpecBase with TryValues {
irmark: String = "Dj5TVJDyRYCn9zta5EdySeY4fyA=",
corr: String = "CID123",
ts: String = "2025-01-01T00:00:00",
err: Option[JsObject] = None
err: Option[JsObject] = None,
accepted: Option[String] = None
): ChrisSubmissionResponse =
ChrisSubmissionResponse(
submissionId = "sub-123",
Expand All @@ -1573,6 +1578,7 @@ class SubmissionServiceSpec extends SpecBase with TryValues {
correlationId = Some(corr),
responseEndPoint = None,
gatewayTimestamp = Some(ts),
acceptedTime = accepted,
error = err
)

Expand Down