From 1fa00d2921b7b1696cdca177af0bac679e748756 Mon Sep 17 00:00:00 2001 From: dc-smith <75583950+dc-smith@users.noreply.github.com> Date: Mon, 3 Nov 2025 15:29:52 +0000 Subject: [PATCH 1/2] Initial GIR response emails --- app/preview/TemplateParams.scala | 62 +++++ .../templates/ServiceIdentifier.scala | 1 + .../templates/TemplateLocator.scala | 4 +- .../templates/pillar2/Pillar2Templates.scala | 56 +++++ .../girSubmissionCriticalErrors.scala.html | 71 ++++++ .../girSubmissionCriticalErrors.scala.txt | 41 ++++ .../girSubmissionGenericErrors.scala.html | 66 ++++++ .../girSubmissionGenericErrors.scala.txt | 38 +++ .../girSubmissionSuccessful.scala.html | 30 +++ .../pillar2/girSubmissionSuccessful.scala.txt | 14 ++ .../templates/TemplateLocatorSpec.scala | 8 +- .../pillar2/Pillar2TemplatesSpec.scala | 218 ++++++++++++++++++ 12 files changed, 606 insertions(+), 3 deletions(-) create mode 100644 app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/Pillar2Templates.scala create mode 100644 app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/girSubmissionCriticalErrors.scala.html create mode 100644 app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/girSubmissionCriticalErrors.scala.txt create mode 100644 app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/girSubmissionGenericErrors.scala.html create mode 100644 app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/girSubmissionGenericErrors.scala.txt create mode 100644 app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/girSubmissionSuccessful.scala.html create mode 100644 app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/girSubmissionSuccessful.scala.txt create mode 100644 test/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/Pillar2TemplatesSpec.scala diff --git a/app/preview/TemplateParams.scala b/app/preview/TemplateParams.scala index 95badcaff..68763148d 100644 --- a/app/preview/TemplateParams.scala +++ b/app/preview/TemplateParams.scala @@ -4009,6 +4009,68 @@ object TemplateParams3 { "lastName" -> "Ferguson", "reference" -> "123ABC", "postcodeFirstPart" -> "BS15" + ), + "pillar2_gir_submission_successful" -> Map( + "referenceId" -> "REF123456789", + "pillar2Id" -> "XMPLR0123456789", + "submissionDate" -> "15/10/2025", + "submissionTime" -> "14:35", + "accountingPeriodStart" -> "01/04/2024", + "accountingPeriodEnd" -> "31/03/2025" + ), + "pillar2_gir_submission_generic_errors" -> Map( + "referenceId" -> "REF987654321", + "pillar2Id" -> "XMPLR9876543210", + "submissionDate" -> "15/10/2025", + "submissionTime" -> "15:20", + "accountingPeriodStart" -> "01/04/2024", + "accountingPeriodEnd" -> "31/03/2025", + "errors" -> stringify(parse("""[ + { + "errorCode": "Error Code 16", + "description": "The structure of the DocRefId is not in the correct format, as set out in the HMRC Pillar 2 Business Rules.", + "docRefIds": "GB2025FRPLRX1234, FR2023GBXPLR1234", + "count": "2" + }, + { + "errorCode": "Error Code 21", + "description": "Where the DocTypeIndic is OECD2 or OECD3, the DocSpec element must contain a CorrDocRefId element.", + "docRefIds": "GB2025GB-PLRX123", + "count": "1" + }, + { + "errorCode": "Error Code 35", + "description": "The MessageRefId must be unique and must not have been used in a previous message.", + "docRefIds": "GB2025PLRX456789", + "count": "1" + } + ]""")) + ), + "pillar2_gir_submission_critical_errors" -> Map( + "referenceId" -> "REF555666777", + "pillar2Id" -> "XMPLR5556667777", + "submissionDate" -> "15/10/2025", + "submissionTime" -> "16:45", + "errors" -> stringify(parse("""[ + { + "errorCode": "Temp Pillar 2 Error Code 1", + "businessRuleName": "Failed Threat Scan", + "errorLevel": "DocRefId(s)", + "description": "Submissions must not include Prohibited Characters or Entity References in the MessageRefId or DocRefId. Submissions must not include Prohibited Characters, these have to be escaped using Entity References in all element values in the DPIBody." + }, + { + "errorCode": "Temp Pillar 2 Error Code 2", + "businessRuleName": "Failed Schema Validation", + "errorLevel": "File", + "description": "The referenced file failed validation against the GIR XML Schema." + }, + { + "errorCode": "Temp Pillar 2 Error Code 4", + "businessRuleName": "Test Data", + "errorLevel": "DocRefId(s)", + "description": "The referenced file contains one or more records with a DocTypeIndic value in the range OECD10-OECD13, indicating test data. As a result, the receiving Competent Authority cannot accept this file as a valid GIR file submission." + } + ]""")) ) ) } diff --git a/app/uk/gov/hmrc/hmrcemailrenderer/templates/ServiceIdentifier.scala b/app/uk/gov/hmrc/hmrcemailrenderer/templates/ServiceIdentifier.scala index 36d660a6d..9e3b218e4 100644 --- a/app/uk/gov/hmrc/hmrcemailrenderer/templates/ServiceIdentifier.scala +++ b/app/uk/gov/hmrc/hmrcemailrenderer/templates/ServiceIdentifier.scala @@ -134,4 +134,5 @@ object ServiceIdentifier { case object Feedback extends ServiceIdentifier { override val name = "feedback" } case object NgrNotify extends ServiceIdentifier { override val name = "ngr-notify" } + case object Pillar2 extends ServiceIdentifier { override val name = "pillar2" } } diff --git a/app/uk/gov/hmrc/hmrcemailrenderer/templates/TemplateLocator.scala b/app/uk/gov/hmrc/hmrcemailrenderer/templates/TemplateLocator.scala index caed24537..2ea3a6416 100644 --- a/app/uk/gov/hmrc/hmrcemailrenderer/templates/TemplateLocator.scala +++ b/app/uk/gov/hmrc/hmrcemailrenderer/templates/TemplateLocator.scala @@ -96,6 +96,7 @@ import uk.gov.hmrc.hmrcemailrenderer.templates.ioss.IossTemplates import uk.gov.hmrc.hmrcemailrenderer.templates.iossNetp.IossNetpTemplates import uk.gov.hmrc.hmrcemailrenderer.templates.ngr.NgrTemplates import uk.gov.hmrc.hmrcemailrenderer.templates.penaltyreform.PenReformTemplates +import uk.gov.hmrc.hmrcemailrenderer.templates.pillar2.Pillar2Templates import uk.gov.hmrc.hmrcemailrenderer.templates.tctr.TctrTemplates import uk.gov.hmrc.hmrcemailrenderer.templates.tctr.TctrTemplates.tctrGroup import uk.gov.hmrc.hmrcemailrenderer.templates.tgp.TgpTemplates @@ -184,7 +185,8 @@ trait TemplateLocator { "IOSS NETP" -> IossNetpTemplates.templates, "TRE" -> treTemplates.templates, FeedbackTemplates.id -> FeedbackTemplates.templates, - "NGR" -> NgrTemplates.templates + "NGR" -> NgrTemplates.templates, + "Pillar 2" -> Pillar2Templates.templates ) lazy val all: Seq[MessageTemplate] = templateGroups.values.flatten.toSeq diff --git a/app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/Pillar2Templates.scala b/app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/Pillar2Templates.scala new file mode 100644 index 000000000..935663550 --- /dev/null +++ b/app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/Pillar2Templates.scala @@ -0,0 +1,56 @@ +/* + * Copyright 2023 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 uk.gov.hmrc.hmrcemailrenderer.templates.pillar2 + +import uk.gov.hmrc.hmrcemailrenderer.domain.{ MessagePriority, MessageTemplate } +import uk.gov.hmrc.hmrcemailrenderer.templates.FromAddress +import uk.gov.hmrc.hmrcemailrenderer.templates.ServiceIdentifier.Pillar2 +import uk.gov.hmrc.hmrcemailrenderer.templates.pillar2.html +import uk.gov.hmrc.hmrcemailrenderer.templates.pillar2.txt + +object Pillar2Templates { + val templates = Seq( + MessageTemplate.create( + templateId = "pillar2_gir_submission_successful", + fromAddress = FromAddress.noReply("pillar2"), + service = Pillar2, + subject = "GloBE Information Return (GIR) – Successful Submission", + plainTemplate = txt.girSubmissionSuccessful.f, + htmlTemplate = html.girSubmissionSuccessful.f, + priority = Some(MessagePriority.Urgent) + ), + MessageTemplate.create( + templateId = "pillar2_gir_submission_generic_errors", + fromAddress = FromAddress.noReply("pillar2"), + service = Pillar2, + subject = "GloBE Information Return (GIR) – Errors Identified. Please Re-submit", + plainTemplate = txt.girSubmissionGenericErrors.f, + htmlTemplate = html.girSubmissionGenericErrors.f, + priority = Some(MessagePriority.Urgent) + ), + MessageTemplate.create( + templateId = "pillar2_gir_submission_critical_errors", + fromAddress = FromAddress.noReply("pillar2"), + service = Pillar2, + subject = + "GloBE Information Return (GIR) – Critical Schema or Business Rule failure. Please check and re-submit.", + plainTemplate = txt.girSubmissionCriticalErrors.f, + htmlTemplate = html.girSubmissionCriticalErrors.f, + priority = Some(MessagePriority.Urgent) + ) + ) +} diff --git a/app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/girSubmissionCriticalErrors.scala.html b/app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/girSubmissionCriticalErrors.scala.html new file mode 100644 index 000000000..b3dda00d0 --- /dev/null +++ b/app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/girSubmissionCriticalErrors.scala.html @@ -0,0 +1,71 @@ +@* + * Copyright 2023 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. + *@ + +@import play.api.libs.json.{ Json, JsObject } + +@(params: Map[String, Any]) + +@errorList = @{ +params("errors") match { +case errors: String => Json.parse(errors).as[List[JsObject]] +case errors: Seq[_] => errors.asInstanceOf[Seq[Map[String, String]]].map(m => Json.toJson(m).as[JsObject]) +case _ => List() +} +} + +@uk.gov.hmrc.hmrcemailrenderer.templates.helpers.html.template_main(params, "GloBE Information Return (GIR) – Critical Schema or Business Rule failure. Please check and re-submit.") { + +
Reference ID: @{params("referenceId")}
+ +Pillar 2 ID: @{params("pillar2Id")}
+ +Your GloBE Information Return submitted on @{params("submissionDate")} at @{params("submissionTime")} has not been processed because it failed one of the following business rules:
+ +Please correct these errors and re-submit your return as soon as possible.
+ +If you have any queries regarding these errors, please contact your software provider.
+ +| Error Code | +Business Rule Name | +Error Level | +Description | +
|---|---|---|---|
| @{(error \ "errorCode").as[String]} | +@{(error \ "businessRuleName").as[String]} | +@{(error \ "errorLevel").as[String]} | +@{(error \ "description").as[String]} | +
From the HMRC Pillar 2 team
+ +} diff --git a/app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/girSubmissionCriticalErrors.scala.txt b/app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/girSubmissionCriticalErrors.scala.txt new file mode 100644 index 000000000..b64c62ec9 --- /dev/null +++ b/app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/girSubmissionCriticalErrors.scala.txt @@ -0,0 +1,41 @@ +@import play.api.libs.json.{ Json, JsObject } + +@(params: Map[String, Any]) + +@errorList = @{ + params("errors") match { + case errors: String => Json.parse(errors).as[List[JsObject]] + case errors: Seq[_] => errors.asInstanceOf[Seq[Map[String, String]]].map(m => Json.toJson(m).as[JsObject]) + case _ => List() + } +} + +GloBE Information Return (GIR) – Critical Schema or Business Rule failure. Please check and re-submit. + +Reference ID: @{params("referenceId")} + +Pillar 2 ID: @{params("pillar2Id")} + +Your GloBE Information Return submitted on @{params("submissionDate")} at @{params("submissionTime")} has not been processed because it failed one of the following business rules: + +- 50005: Failed threat scan – the file contains prohibited characters or invalid entity references +- 50007: Failed Schema Validation – the file failed validation against the OECD GIR XML Schema +- 50010: Test data – the file has 'DocTypeIndic' values in the range OECD10-OECD13 +- Temporary Error Code 3: Empty Elements – the file format is incorrect at either file or record level. + +Please correct these errors and re-submit your return as soon as possible. + +If you have any queries regarding these errors, please contact your software provider. + +CRITICAL ERRORS IDENTIFIED: +@for(error <- errorList) { +Error Code: @{(error \ "errorCode").as[String]} +Business Rule Name: @{(error \ "businessRuleName").as[String]} +Error Level: @{(error \ "errorLevel").as[String]} +Description: @{(error \ "description").as[String]} +--- +} + +From the HMRC Pillar 2 team + +@{uk.gov.hmrc.hmrcemailrenderer.templates.helpers.txt.template_footer()} diff --git a/app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/girSubmissionGenericErrors.scala.html b/app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/girSubmissionGenericErrors.scala.html new file mode 100644 index 000000000..470147f45 --- /dev/null +++ b/app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/girSubmissionGenericErrors.scala.html @@ -0,0 +1,66 @@ +@* + * Copyright 2023 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. + *@ + +@import play.api.libs.json.{ Json, JsObject } + +@(params: Map[String, Any]) + +@errorList = @{ +params("errors") match { +case errors: String => Json.parse(errors).as[List[JsObject]] +case errors: Seq[_] => errors.asInstanceOf[Seq[Map[String, String]]].map(m => Json.toJson(m).as[JsObject]) +case _ => List() +} +} + +@uk.gov.hmrc.hmrcemailrenderer.templates.helpers.html.template_main(params, "GloBE Information Return (GIR) – Errors Identified. Please Re-submit") { + +Reference ID: @{params("referenceId")}
+ +Pillar 2 ID: @{params("pillar2Id")}
+ +This is to confirm that HM Revenue and Customs received your GloBE Information Return on @{params("submissionDate")} at @{params("submissionTime")} for the accounting period @{params("accountingPeriodStart")} to @{params("accountingPeriodEnd")}.
+ +However, validation of this return has identified the errors listed below.
+ +Please correct these errors and re-submit your return as soon as possible.
+ +If you have any queries regarding these errors, please contact your software provider.
+ +| Error Code | +Description | +DocRefId in Error | +Count | +
|---|---|---|---|
| @{(error \ "errorCode").as[String]} | +@{(error \ "description").as[String]} | +@{(error \ "docRefIds").asOpt[String].getOrElse("")} | +@{(error \ "count").as[String]} | +
From the HMRC Pillar 2 team
+ +} diff --git a/app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/girSubmissionGenericErrors.scala.txt b/app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/girSubmissionGenericErrors.scala.txt new file mode 100644 index 000000000..eef846299 --- /dev/null +++ b/app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/girSubmissionGenericErrors.scala.txt @@ -0,0 +1,38 @@ +@import play.api.libs.json.{ Json, JsObject } + +@(params: Map[String, Any]) + +@errorList = @{ + params("errors") match { + case errors: String => Json.parse(errors).as[List[JsObject]] + case errors: Seq[_] => errors.asInstanceOf[Seq[Map[String, String]]].map(m => Json.toJson(m).as[JsObject]) + case _ => List() + } +} + +GloBE Information Return (GIR) – Errors Identified. Please Re-submit + +Reference ID: @{params("referenceId")} + +Pillar 2 ID: @{params("pillar2Id")} + +This is to confirm that HM Revenue and Customs received your GloBE Information Return on @{params("submissionDate")} at @{params("submissionTime")} for the accounting period @{params("accountingPeriodStart")} to @{params("accountingPeriodEnd")}. + +However, validation of this return has identified the errors listed below. + +Please correct these errors and re-submit your return as soon as possible. + +If you have any queries regarding these errors, please contact your software provider. + +ERRORS IDENTIFIED: +@for(error <- errorList) { +Error Code: @{(error \ "errorCode").as[String]} +Description: @{(error \ "description").as[String]} +DocRefId in Error: @{(error \ "docRefIds").asOpt[String].getOrElse("")} +Count: @{(error \ "count").as[String]} +--- +} + +From the HMRC Pillar 2 team + +@{uk.gov.hmrc.hmrcemailrenderer.templates.helpers.txt.template_footer()} diff --git a/app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/girSubmissionSuccessful.scala.html b/app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/girSubmissionSuccessful.scala.html new file mode 100644 index 000000000..a812097c5 --- /dev/null +++ b/app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/girSubmissionSuccessful.scala.html @@ -0,0 +1,30 @@ +@* + * Copyright 2023 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. + *@ + +@(params: Map[String, Any]) +@uk.gov.hmrc.hmrcemailrenderer.templates.helpers.html.template_main(params, "GloBE Information Return (GIR) – Successful Submission") { + +Reference ID: @{params("referenceId")}
+ +Pillar 2 ID: @{params("pillar2Id")}
+ +This is to confirm that HM Revenue and Customs received your GloBE Information Return on @{params("submissionDate")} at @{params("submissionTime")} for the accounting period @{params("accountingPeriodStart")} to @{params("accountingPeriodEnd")}.
+ +If you have any queries, please contact the Pillar 2 team at: pillar2mailbox@@hmrc.gov.uk
+ +From the HMRC Pillar 2 team
+ +} diff --git a/app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/girSubmissionSuccessful.scala.txt b/app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/girSubmissionSuccessful.scala.txt new file mode 100644 index 000000000..a27c3e9a3 --- /dev/null +++ b/app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/girSubmissionSuccessful.scala.txt @@ -0,0 +1,14 @@ +@(params: Map[String, Any])GloBE Information Return (GIR) – Successful Submission + +Reference ID: @{params("referenceId")} + +Pillar 2 ID: @{params("pillar2Id")} + +This is to confirm that HM Revenue and Customs received your GloBE Information Return on @{params("submissionDate")} at @{params("submissionTime")} for the accounting period @{params("accountingPeriodStart")} to @{params("accountingPeriodEnd")}. + +If you have any queries, please contact the Pillar 2 team at: +pillar2mailbox@@hmrc.gov.uk + +From the HMRC Pillar 2 team + +@{uk.gov.hmrc.hmrcemailrenderer.templates.helpers.txt.template_footer()} diff --git a/test/uk/gov/hmrc/hmrcemailrenderer/templates/TemplateLocatorSpec.scala b/test/uk/gov/hmrc/hmrcemailrenderer/templates/TemplateLocatorSpec.scala index c13a8d377..66638b852 100644 --- a/test/uk/gov/hmrc/hmrcemailrenderer/templates/TemplateLocatorSpec.scala +++ b/test/uk/gov/hmrc/hmrcemailrenderer/templates/TemplateLocatorSpec.scala @@ -147,7 +147,8 @@ class TemplateLocatorSpec extends AnyWordSpecLike with should.Matchers with Opti "CIR", "IOSS NETP", "TRE", - "NGR" + "NGR", + "Pillar 2" ) } @@ -1097,7 +1098,10 @@ class TemplateLocatorSpec extends AnyWordSpecLike with should.Matchers with Opti "tgp_download_record_failure_notification_email", "tgp_download_record_failure_notification_email_cy", "ngr_registration_successful", - "ngr_add_property_request_sent" + "ngr_add_property_request_sent", + "pillar2_gir_submission_successful", + "pillar2_gir_submission_generic_errors", + "pillar2_gir_submission_critical_errors" ) } } diff --git a/test/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/Pillar2TemplatesSpec.scala b/test/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/Pillar2TemplatesSpec.scala new file mode 100644 index 000000000..a005eb93e --- /dev/null +++ b/test/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/Pillar2TemplatesSpec.scala @@ -0,0 +1,218 @@ +/* + * Copyright 2023 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 uk.gov.hmrc.hmrcemailrenderer.templates.pillar2 + +import org.scalatestplus.play.PlaySpec +import uk.gov.hmrc.hmrcemailrenderer.domain.{ MessagePriority, MessageTemplate } +import uk.gov.hmrc.hmrcemailrenderer.templates.CommonParamsForSpec +import uk.gov.hmrc.hmrcemailrenderer.templates.ServiceIdentifier.Pillar2 + +class Pillar2TemplatesSpec extends PlaySpec with CommonParamsForSpec { + + "GIR Successful Submission Template" must { + + val successTemplate: MessageTemplate = MessageTemplate.create( + templateId = "pillar2_gir_submission_successful", + fromAddress = "pillar2@notifications.service.gov.uk", + service = Pillar2, + subject = "GloBE Information Return (GIR) – Successful Submission", + plainTemplate = txt.girSubmissionSuccessful.f, + htmlTemplate = html.girSubmissionSuccessful.f, + priority = Some(MessagePriority.Urgent) + ) + + val params = commonParameters ++ Map( + "referenceId" -> "REF123456", + "pillar2Id" -> "XMPLR0123456789", + "submissionDate" -> "01/01/2024", + "submissionTime" -> "14:30", + "accountingPeriodStart" -> "01/04/2023", + "accountingPeriodEnd" -> "31/03/2024" + ) + + "include correct subject" in { + successTemplate.subject(params) mustBe "GloBE Information Return (GIR) – Successful Submission" + } + + "include htmlTemplate body with correct content" in { + val htmlContent = successTemplate.htmlTemplate(params).toString + htmlContent must include("GloBE Information Return") + htmlContent must include("Reference ID: REF123456") + htmlContent must include("Pillar 2 ID: XMPLR0123456789") + htmlContent must include( + "This is to confirm that HM Revenue and Customs received your GloBE Information Return on 01/01/2024 at 14:30" + ) + htmlContent must include("for the accounting period 01/04/2023 to 31/03/2024") + htmlContent must include("pillar2mailbox@hmrc.gov.uk") + htmlContent must include("From the HMRC Pillar 2 team") + } + + "include txtTemplate body with correct content" in { + val txtContent = successTemplate.plainTemplate(params).toString + txtContent must include("GloBE Information Return") + txtContent must include("Reference ID: REF123456") + txtContent must include("Pillar 2 ID: XMPLR0123456789") + txtContent must include( + "This is to confirm that HM Revenue and Customs received your GloBE Information Return on 01/01/2024 at 14:30" + ) + txtContent must include("for the accounting period 01/04/2023 to 31/03/2024") + txtContent must include("pillar2mailbox@hmrc.gov.uk") + txtContent must include("From the HMRC Pillar 2 team") + } + } + + "GIR Generic Errors Template" must { + + val genericErrorsTemplate: MessageTemplate = MessageTemplate.create( + templateId = "pillar2_gir_submission_generic_errors", + fromAddress = "pillar2@notifications.service.gov.uk", + service = Pillar2, + subject = "GloBE Information Return (GIR) – Errors Identified. Please Re-submit", + plainTemplate = txt.girSubmissionGenericErrors.f, + htmlTemplate = html.girSubmissionGenericErrors.f, + priority = Some(MessagePriority.Urgent) + ) + + val errors = Seq( + Map( + "errorCode" -> "Error Code 16", + "description" -> "The structure of the DocRefId is not in the correct format", + "docRefIds" -> "GB2025FRPLRX1234, FR2023GBXPLR1234", + "count" -> "2" + ), + Map( + "errorCode" -> "Error Code 21", + "description" -> "Where the DocTypeIndic is OECD2 or OECD3, the DocSpec element must contain a CorrDocRefId element", + "docRefIds" -> "GB2025GB-PLRX123", + "count" -> "1" + ) + ) + + val paramsBase = commonParameters ++ Map( + "referenceId" -> "REF123456", + "pillar2Id" -> "XMPLR0123456789", + "submissionDate" -> "01/01/2024", + "submissionTime" -> "14:30", + "accountingPeriodStart" -> "01/04/2023", + "accountingPeriodEnd" -> "31/03/2024" + ) + + val params: Map[String, Any] = paramsBase ++ Map("errors" -> errors) + + "include correct subject" in { + genericErrorsTemplate.subject( + paramsBase + ) mustBe "GloBE Information Return (GIR) – Errors Identified. Please Re-submit" + } + + "include htmlTemplate body with error table" in { + val htmlContent = genericErrorsTemplate.htmlTemplate(params).toString + htmlContent must include("GloBE Information Return") + htmlContent must include("Reference ID: REF123456") + htmlContent must include("Pillar 2 ID: XMPLR0123456789") + htmlContent must include("However, validation of this return has identified the errors listed below") + htmlContent must include("Please correct these errors and re-submit your return as soon as possible") + htmlContent must include("Error Code 16") + htmlContent must include("The structure of the DocRefId is not in the correct format") + htmlContent must include("GB2025FRPLRX1234, FR2023GBXPLR1234") + htmlContent must include("Error Code 21") + htmlContent must include("From the HMRC Pillar 2 team") + } + + "include txtTemplate body with errors" in { + val txtContent = genericErrorsTemplate.plainTemplate(params).toString + txtContent must include("GloBE Information Return") + txtContent must include("Reference ID: REF123456") + txtContent must include("However, validation of this return has identified the errors listed below") + txtContent must include("Error Code 16") + txtContent must include("Error Code 21") + txtContent must include("From the HMRC Pillar 2 team") + } + } + + "GIR Critical Errors Template" must { + + val criticalErrorsTemplate: MessageTemplate = MessageTemplate.create( + templateId = "pillar2_gir_submission_critical_errors", + fromAddress = "pillar2@notifications.service.gov.uk", + service = Pillar2, + subject = + "GloBE Information Return (GIR) – Critical Schema or Business Rule failure. Please check and re-submit.", + plainTemplate = txt.girSubmissionCriticalErrors.f, + htmlTemplate = html.girSubmissionCriticalErrors.f, + priority = Some(MessagePriority.Urgent) + ) + + val errors = Seq( + Map( + "errorCode" -> "Temp Pillar 2 Error Code 1", + "businessRuleName" -> "Failed Threat Scan", + "errorLevel" -> "DocRefId(s)", + "description" -> "Submissions must not include Prohibited Characters or Entity References" + ), + Map( + "errorCode" -> "Temp Pillar 2 Error Code 2", + "businessRuleName" -> "Failed Schema Validation", + "errorLevel" -> "File", + "description" -> "The referenced file failed validation against the GIR XML Schema" + ) + ) + + val paramsBase = commonParameters ++ Map( + "referenceId" -> "REF123456", + "pillar2Id" -> "XMPLR0123456789", + "submissionDate" -> "01/01/2024", + "submissionTime" -> "14:30" + ) + + val params: Map[String, Any] = paramsBase ++ Map("errors" -> errors) + + "include correct subject" in { + criticalErrorsTemplate.subject( + paramsBase + ) mustBe "GloBE Information Return (GIR) – Critical Schema or Business Rule failure. Please check and re-submit." + } + + "include htmlTemplate body with critical error details" in { + val htmlContent = criticalErrorsTemplate.htmlTemplate(params).toString + htmlContent must include("GloBE Information Return") + htmlContent must include("Reference ID: REF123456") + htmlContent must include("Pillar 2 ID: XMPLR0123456789") + htmlContent must include("has not been processed because it failed one of the following business rules") + htmlContent must include("50005: Failed threat scan") + htmlContent must include("50007: Failed Schema Validation") + htmlContent must include("50010: Test data") + htmlContent must include("Temporary Error Code 3: Empty Elements") + htmlContent must include("Temp Pillar 2 Error Code 1") + htmlContent must include("Failed Threat Scan") + htmlContent must include("Temp Pillar 2 Error Code 2") + htmlContent must include("Failed Schema Validation") + htmlContent must include("From the HMRC Pillar 2 team") + } + + "include txtTemplate body with critical errors" in { + val txtContent = criticalErrorsTemplate.plainTemplate(params).toString + txtContent must include("GloBE Information Return") + txtContent must include("Reference ID: REF123456") + txtContent must include("has not been processed because it failed one of the following business rules") + txtContent must include("50005: Failed threat scan") + txtContent must include("Temp Pillar 2 Error Code 1") + txtContent must include("Failed Threat Scan") + txtContent must include("From the HMRC Pillar 2 team") + } + } +} From ff298ec3855fbdfa7c9d2b6c4d79987aa3012cec Mon Sep 17 00:00:00 2001 From: dc-smith <75583950+dc-smith@users.noreply.github.com> Date: Mon, 3 Nov 2025 16:58:20 +0000 Subject: [PATCH 2/2] Content updates --- .../templates/pillar2/Pillar2DateTimes.scala | 34 ++++++++ .../templates/pillar2/Pillar2Templates.scala | 7 +- .../girSubmissionCriticalErrors.scala.html | 23 +++--- .../girSubmissionCriticalErrors.scala.txt | 13 +-- .../girSubmissionGenericErrors.scala.html | 23 +++--- .../girSubmissionGenericErrors.scala.txt | 13 +-- .../girSubmissionSuccessful.scala.html | 12 ++- .../pillar2/girSubmissionSuccessful.scala.txt | 13 +-- .../pillar2/Pillar2TemplatesSpec.scala | 79 +++++++++++-------- 9 files changed, 140 insertions(+), 77 deletions(-) create mode 100644 app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/Pillar2DateTimes.scala diff --git a/app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/Pillar2DateTimes.scala b/app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/Pillar2DateTimes.scala new file mode 100644 index 000000000..39378a7f6 --- /dev/null +++ b/app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/Pillar2DateTimes.scala @@ -0,0 +1,34 @@ +/* + * Copyright 2025 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 uk.gov.hmrc.hmrcemailrenderer.templates.pillar2 + +import java.time.{ LocalDate, LocalTime } +import java.time.format.DateTimeFormatter + +object Pillar2DateTimes { + + def ukAllNumericDateToUserFacing(raw: String): String = + LocalDate + .parse( + raw, + DateTimeFormatter.ofPattern("dd/MM/yyyy") + ) + .format(DateTimeFormatter.ofPattern("d MMMM YYYY")) + + def toTwelveHourUserFacing(raw: String): String = + LocalTime.parse(raw).format(DateTimeFormatter.ofPattern("h:mma")) +} diff --git a/app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/Pillar2Templates.scala b/app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/Pillar2Templates.scala index 935663550..452fe9621 100644 --- a/app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/Pillar2Templates.scala +++ b/app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/Pillar2Templates.scala @@ -28,7 +28,7 @@ object Pillar2Templates { templateId = "pillar2_gir_submission_successful", fromAddress = FromAddress.noReply("pillar2"), service = Pillar2, - subject = "GloBE Information Return (GIR) – Successful Submission", + subject = "Successful submission of GloBE Information Return (GIR) – Pillar 2 Top-up Taxes", plainTemplate = txt.girSubmissionSuccessful.f, htmlTemplate = html.girSubmissionSuccessful.f, priority = Some(MessagePriority.Urgent) @@ -37,7 +37,7 @@ object Pillar2Templates { templateId = "pillar2_gir_submission_generic_errors", fromAddress = FromAddress.noReply("pillar2"), service = Pillar2, - subject = "GloBE Information Return (GIR) – Errors Identified. Please Re-submit", + subject = "There is a problem with your GloBE Information Return (GIR) - Pillar 2 Top-up Taxes", plainTemplate = txt.girSubmissionGenericErrors.f, htmlTemplate = html.girSubmissionGenericErrors.f, priority = Some(MessagePriority.Urgent) @@ -46,8 +46,7 @@ object Pillar2Templates { templateId = "pillar2_gir_submission_critical_errors", fromAddress = FromAddress.noReply("pillar2"), service = Pillar2, - subject = - "GloBE Information Return (GIR) – Critical Schema or Business Rule failure. Please check and re-submit.", + subject = "There is a problem with your GloBE Information Return (GIR) - Pillar 2 Top-up Taxes", plainTemplate = txt.girSubmissionCriticalErrors.f, htmlTemplate = html.girSubmissionCriticalErrors.f, priority = Some(MessagePriority.Urgent) diff --git a/app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/girSubmissionCriticalErrors.scala.html b/app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/girSubmissionCriticalErrors.scala.html index b3dda00d0..27ecc21fc 100644 --- a/app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/girSubmissionCriticalErrors.scala.html +++ b/app/uk/gov/hmrc/hmrcemailrenderer/templates/pillar2/girSubmissionCriticalErrors.scala.html @@ -15,24 +15,27 @@ *@ @import play.api.libs.json.{ Json, JsObject } +@import uk.gov.hmrc.hmrcemailrenderer.templates.pillar2.Pillar2DateTimes.* @(params: Map[String, Any]) @errorList = @{ -params("errors") match { -case errors: String => Json.parse(errors).as[List[JsObject]] -case errors: Seq[_] => errors.asInstanceOf[Seq[Map[String, String]]].map(m => Json.toJson(m).as[JsObject]) -case _ => List() -} + params("errors") match { + case errors: String => Json.parse(errors).as[List[JsObject]] + case errors: Seq[_] => errors.asInstanceOf[Seq[Map[String, String]]].map(m => Json.toJson(m).as[JsObject]) + case _ => List() + } } -@uk.gov.hmrc.hmrcemailrenderer.templates.helpers.html.template_main(params, "GloBE Information Return (GIR) – Critical Schema or Business Rule failure. Please check and re-submit.") { +@uk.gov.hmrc.hmrcemailrenderer.templates.helpers.html.template_main(params, "Critical Schema or Business Rule failure - GloBE Information Return (GIR)") { -Reference ID: @{params("referenceId")}
+GIR Reference ID: @{params("referenceId")}
Pillar 2 ID: @{params("pillar2Id")}
-Your GloBE Information Return submitted on @{params("submissionDate")} at @{params("submissionTime")} has not been processed because it failed one of the following business rules:
+Received: @{toTwelveHourUserFacing(params("submissionTime").toString)} on @{ukAllNumericDateToUserFacing(params("submissionDate").toString)}
+ +Your GIR has not been processed because it failed one of the following business rules:
Please correct these errors and re-submit your return as soon as possible.
+You must correct these errors and re-submit your return as soon as possible.
-If you have any queries regarding these errors, please contact your software provider.
+If you have any queries regarding these errors you should contact your software provider.