From 483e13046ce8e20d634eda234de74562276443c6 Mon Sep 17 00:00:00 2001 From: Arunima George Date: Thu, 24 Apr 2025 09:10:28 +0100 Subject: [PATCH 01/16] TD-5474: Create a new messaging service project --- .../Interfaces/IGovNotifyService.cs | 29 ++++ .../LearningHub.Nhs.MessagingService.csproj | 16 +++ .../Model/MessagingServiceModel.cs | 21 +++ .../Model/SendEmailRequest.cs | 28 ++++ .../Model/SendSmsRequest.cs | 28 ++++ .../Services/GovNotifyService.cs | 91 +++++++++++++ LearningHub.Nhs.MessagingService/Startup.cs | 25 ++++ LearningHub.Nhs.WebUI.sln | 13 ++ .../GovNotifyMessagingController.cs | 78 +++++++++++ .../LearningHub.NHS.OpenAPI.csproj | 1 + OpenAPI/LearningHub.Nhs.OpenApi/Startup.cs | 2 + .../SwaggerDefinitions/v1.3.0.json | 124 ++++++++++++++++++ .../LearningHub.Nhs.OpenApi/appsettings.json | 3 + 13 files changed, 459 insertions(+) create mode 100644 LearningHub.Nhs.MessagingService/Interfaces/IGovNotifyService.cs create mode 100644 LearningHub.Nhs.MessagingService/LearningHub.Nhs.MessagingService.csproj create mode 100644 LearningHub.Nhs.MessagingService/Model/MessagingServiceModel.cs create mode 100644 LearningHub.Nhs.MessagingService/Model/SendEmailRequest.cs create mode 100644 LearningHub.Nhs.MessagingService/Model/SendSmsRequest.cs create mode 100644 LearningHub.Nhs.MessagingService/Services/GovNotifyService.cs create mode 100644 LearningHub.Nhs.MessagingService/Startup.cs create mode 100644 OpenAPI/LearningHub.Nhs.OpenApi/Controllers/GovNotifyMessagingController.cs diff --git a/LearningHub.Nhs.MessagingService/Interfaces/IGovNotifyService.cs b/LearningHub.Nhs.MessagingService/Interfaces/IGovNotifyService.cs new file mode 100644 index 000000000..23d0d3738 --- /dev/null +++ b/LearningHub.Nhs.MessagingService/Interfaces/IGovNotifyService.cs @@ -0,0 +1,29 @@ +namespace LearningHub.Nhs.MessagingService.Interfaces +{ + using System.Collections.Generic; + using System.Threading.Tasks; + + /// + /// IMessageServices. + /// + public interface IGovNotifyService + { + /// + /// Send EmailAsync. + /// + /// email. + /// templateId. + /// personalisation. + /// The . + Task SendEmailAsync(string email, string templateId, Dictionary personalisation); + + /// + /// Send SmsAsync. + /// + /// phoneNumber. + /// templateId. + /// personalisation. + /// The . + Task SendSmsAsync(string phoneNumber, string templateId, Dictionary personalisation); + } +} diff --git a/LearningHub.Nhs.MessagingService/LearningHub.Nhs.MessagingService.csproj b/LearningHub.Nhs.MessagingService/LearningHub.Nhs.MessagingService.csproj new file mode 100644 index 000000000..d21593e42 --- /dev/null +++ b/LearningHub.Nhs.MessagingService/LearningHub.Nhs.MessagingService.csproj @@ -0,0 +1,16 @@ + + + + net8.0 + enable + true + + + + + + + + + + diff --git a/LearningHub.Nhs.MessagingService/Model/MessagingServiceModel.cs b/LearningHub.Nhs.MessagingService/Model/MessagingServiceModel.cs new file mode 100644 index 000000000..66a3f210e --- /dev/null +++ b/LearningHub.Nhs.MessagingService/Model/MessagingServiceModel.cs @@ -0,0 +1,21 @@ +namespace LearningHub.Nhs.MessagingService.Model +{ + /// + /// MessagingServiceModel. + /// + public class MessagingServiceModel + { + /// + /// Initializes a new instance of the class. + /// + public MessagingServiceModel() + { + // Current = this; + } + + /// + /// Gets or Sets ApiKey. + /// + public string GovNotifyApiKey { get; set; } = string.Empty; + } +} diff --git a/LearningHub.Nhs.MessagingService/Model/SendEmailRequest.cs b/LearningHub.Nhs.MessagingService/Model/SendEmailRequest.cs new file mode 100644 index 000000000..da0044425 --- /dev/null +++ b/LearningHub.Nhs.MessagingService/Model/SendEmailRequest.cs @@ -0,0 +1,28 @@ +namespace LearningHub.Nhs.MessagingService.Model +{ + using System.Collections.Generic; + using System.ComponentModel.DataAnnotations; + + /// + /// Defines the . + /// + public class SendEmailRequest + { + /// + /// Gets or Sets the Email. + /// + [Required] + public string Email { get; set; } + + /// + /// Gets or Sets the TemplateId. + /// + [Required] + public string TemplateId { get; set; } + + /// + /// Gets or Sets the Personalisation. + /// + public Dictionary Personalisation { get; set; } + } +} diff --git a/LearningHub.Nhs.MessagingService/Model/SendSmsRequest.cs b/LearningHub.Nhs.MessagingService/Model/SendSmsRequest.cs new file mode 100644 index 000000000..cb2481cfe --- /dev/null +++ b/LearningHub.Nhs.MessagingService/Model/SendSmsRequest.cs @@ -0,0 +1,28 @@ +namespace LearningHub.Nhs.MessagingService.Model +{ + using System.Collections.Generic; + using System.ComponentModel.DataAnnotations; + + /// + /// Defines the . + /// + public class SendSmsRequest + { + /// + /// Gets or Sets the PhoneNumber. + /// + [Required] + public string PhoneNumber { get; set; } + + /// + /// Gets or Sets the TemplateId. + /// + [Required] + public string TemplateId { get; set; } + + /// + /// Gets or Sets the Personalisation. + /// + public Dictionary Personalisation { get; set; } + } +} diff --git a/LearningHub.Nhs.MessagingService/Services/GovNotifyService.cs b/LearningHub.Nhs.MessagingService/Services/GovNotifyService.cs new file mode 100644 index 000000000..b81c8e7b2 --- /dev/null +++ b/LearningHub.Nhs.MessagingService/Services/GovNotifyService.cs @@ -0,0 +1,91 @@ +namespace LearningHub.Nhs.MessagingService.Services +{ + using System; + using System.Collections.Generic; + using System.Text.Json; + using System.Threading.Tasks; + using LearningHub.Nhs.MessagingService.Interfaces; + using LearningHub.Nhs.MessagingService.Model; + using Microsoft.Extensions.Options; + using Notify.Client; + + /// + /// GovNotify Service class. + /// + public class GovNotifyService : IGovNotifyService + { + private readonly NotificationClient client; + + /// + /// Initializes a new instance of the class. + /// GovNotifyService. + /// + /// The Messaging Service Model. + public GovNotifyService(IOptions options) + { + this.client = new NotificationClient(options.Value.GovNotifyApiKey); + } + + /// + /// Sends an email via the UK Gov.Notify service. + /// + /// The recipient's email address. + /// The ID of the Gov.Notify template to be used for the email. + /// + /// A dictionary containing key-value pairs for personalising the email template. + /// Keys should match the placeholders in the Gov.Notify template. + /// + /// + /// A unique message ID representing the queued email. + /// + public async Task SendEmailAsync(string email, string templateId, Dictionary personalisation) + { + var normalisedPersonlisation = new Dictionary(); + foreach (var item in personalisation) + { + if (item.Value is JsonElement element) + { + normalisedPersonlisation[item.Key] = element.ToString(); + } + else + { + normalisedPersonlisation[item.Key] = item.Value; + } + } + + var response = await this.client.SendEmailAsync(email, templateId, normalisedPersonlisation); + return response.id; + } + + /// + /// Sends an SMS via the UK Gov.Notify service. + /// + /// The recipient's phone number. + /// The ID of the Gov.Notify template to be used for the SMS. + /// + /// A dictionary containing key-value pairs for personalising the SMS template. + /// Keys should match the placeholders in the Gov.Notify template. + /// + /// + /// A unique message ID representing the queued SMS. + /// + public async Task SendSmsAsync(string phoneNumber, string templateId, Dictionary personalisation) + { + var normalisedPersonlisation = new Dictionary(); + foreach (var item in personalisation) + { + if (item.Value is JsonElement element) + { + normalisedPersonlisation[item.Key] = element.ToString(); + } + else + { + normalisedPersonlisation[item.Key] = item.Value; + } + } + + var response = await this.client.SendSmsAsync(phoneNumber, templateId, normalisedPersonlisation); + return response.id; + } + } +} diff --git a/LearningHub.Nhs.MessagingService/Startup.cs b/LearningHub.Nhs.MessagingService/Startup.cs new file mode 100644 index 000000000..522b98bda --- /dev/null +++ b/LearningHub.Nhs.MessagingService/Startup.cs @@ -0,0 +1,25 @@ +namespace LearningHub.Nhs.MessagingService +{ + using LearningHub.Nhs.MessagingService.Interfaces; + using LearningHub.Nhs.MessagingService.Model; + using LearningHub.Nhs.MessagingService.Services; + using Microsoft.Extensions.Configuration; + using Microsoft.Extensions.DependencyInjection; + + /// + /// Contains methods to configure the project to be called in an API startup class. + /// + public static class Startup + { + /// + /// Registers the implementations in the project with ASP.NET DI. + /// + /// The IServiceCollection. + /// The IConfiguration. + public static void AddMessagingServices(this IServiceCollection services, IConfiguration configuration) + { + services.Configure(configuration.GetSection("GovNotify")); + services.AddScoped(); + } + } +} diff --git a/LearningHub.Nhs.WebUI.sln b/LearningHub.Nhs.WebUI.sln index 5aea6885f..e4ca88071 100644 --- a/LearningHub.Nhs.WebUI.sln +++ b/LearningHub.Nhs.WebUI.sln @@ -81,6 +81,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LearningHub.Nhs.ReportApi.S EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LearningHub.Nhs.WebUI.AutomatedUiTests", "LearningHub.Nhs.WebUI.AutomatedUiTests\LearningHub.Nhs.WebUI.AutomatedUiTests.csproj", "{A84EC50B-2B01-4819-A2B1-BD867B7595CA}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MessagingService", "MessagingService", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LearningHub.Nhs.MessagingService", "LearningHub.Nhs.MessagingService\LearningHub.Nhs.MessagingService.csproj", "{713B0099-60E3-4D28-980F-448FC68BC7EE}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -345,6 +349,14 @@ Global {A84EC50B-2B01-4819-A2B1-BD867B7595CA}.Release|Any CPU.Build.0 = Release|Any CPU {A84EC50B-2B01-4819-A2B1-BD867B7595CA}.Release|x64.ActiveCfg = Release|Any CPU {A84EC50B-2B01-4819-A2B1-BD867B7595CA}.Release|x64.Build.0 = Release|Any CPU + {713B0099-60E3-4D28-980F-448FC68BC7EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {713B0099-60E3-4D28-980F-448FC68BC7EE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {713B0099-60E3-4D28-980F-448FC68BC7EE}.Debug|x64.ActiveCfg = Debug|Any CPU + {713B0099-60E3-4D28-980F-448FC68BC7EE}.Debug|x64.Build.0 = Debug|Any CPU + {713B0099-60E3-4D28-980F-448FC68BC7EE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {713B0099-60E3-4D28-980F-448FC68BC7EE}.Release|Any CPU.Build.0 = Release|Any CPU + {713B0099-60E3-4D28-980F-448FC68BC7EE}.Release|x64.ActiveCfg = Release|Any CPU + {713B0099-60E3-4D28-980F-448FC68BC7EE}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -380,6 +392,7 @@ Global {E585A74A-F358-4446-B10E-0FF07B4FF601} = {A4209011-1740-4902-B889-2F2FAF98383F} {AAC8306E-1DEB-460D-84C7-40166D189B88} = {A4209011-1740-4902-B889-2F2FAF98383F} {6167F037-166C-4C5A-81BE-55618E77D4E8} = {A4209011-1740-4902-B889-2F2FAF98383F} + {713B0099-60E3-4D28-980F-448FC68BC7EE} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {1ECA38C8-7C69-4DE6-8293-852C603F4217} diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/GovNotifyMessagingController.cs b/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/GovNotifyMessagingController.cs new file mode 100644 index 000000000..05066a292 --- /dev/null +++ b/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/GovNotifyMessagingController.cs @@ -0,0 +1,78 @@ +namespace LearningHub.NHS.OpenAPI.Controllers +{ + using System; + using System.Threading.Tasks; + using LearningHub.Nhs.MessagingService.Interfaces; + using LearningHub.Nhs.MessagingService.Model; + using Microsoft.AspNetCore.Authorization; + using Microsoft.AspNetCore.Mvc; + + /// + /// GovNotify Messaging Controller. + /// + [Route("GovNotifyMessage")] + [Authorize] + public class GovNotifyMessagingController : OpenApiControllerBase + { + private readonly IGovNotifyService messageService; + + /// + /// Initializes a new instance of the class. + /// + /// The catalogue service. + public GovNotifyMessagingController(IGovNotifyService messageService) + { + this.messageService = messageService; + } + + /// + /// Sends an email using UK Gov.Notify. + /// + /// personalisation. + /// The . + [Route("sendemail")] + [HttpPost] + public async Task SendEmailAsync([FromBody] SendEmailRequest request) + { + try + { + if (string.IsNullOrWhiteSpace(request.Email) || string.IsNullOrWhiteSpace(request.TemplateId)) + { + return this.BadRequest("Email and template ID are required"); + } + + var response = await this.messageService.SendEmailAsync(request.Email, request.TemplateId, request.Personalisation); + return this.Ok(response); + } + catch (Exception ex) + { + return this.Ok(ex.Message); + } + } + + /// + /// Sends a sms using UK Gov.Notify. + /// + /// SendSmsRequest. + /// The . + [Route("sendsms")] + [HttpPost] + public async Task SendSmsAsync([FromBody] SendSmsRequest request) + { + try + { + if (string.IsNullOrWhiteSpace(request.PhoneNumber) || string.IsNullOrWhiteSpace(request.TemplateId)) + { + return this.BadRequest("phoneNumber and template ID are required"); + } + + var response = await this.messageService.SendSmsAsync(request.PhoneNumber, request.TemplateId, request.Personalisation); + return this.Ok(response); + } + catch (Exception ex) + { + return this.Ok(ex.Message); + } + } + } +} diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj b/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj index 83639e186..6ed354944 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj @@ -31,6 +31,7 @@ + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/Startup.cs b/OpenAPI/LearningHub.Nhs.OpenApi/Startup.cs index 627401b12..f3dc3f51b 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi/Startup.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi/Startup.cs @@ -30,6 +30,7 @@ namespace LearningHub.NHS.OpenAPI using System.Configuration; using System; using LearningHub.Nhs.Models.Extensions; + using LearningHub.Nhs.MessagingService; /// /// The Startup class. @@ -84,6 +85,7 @@ public void ConfigureServices(IServiceCollection services) services.AddApplicationInsightsTelemetry(); services.AddControllers(options => options.Filters.Add(new HttpResponseExceptionFilter())); services.AddControllers(opt => { opt.Filters.Add(new AuthorizeFilter()); }); + services.AddMessagingServices(this.Configuration); services.AddSwaggerGen( c => { diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/SwaggerDefinitions/v1.3.0.json b/OpenAPI/LearningHub.Nhs.OpenApi/SwaggerDefinitions/v1.3.0.json index 0cde7cef1..9633b6117 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi/SwaggerDefinitions/v1.3.0.json +++ b/OpenAPI/LearningHub.Nhs.OpenApi/SwaggerDefinitions/v1.3.0.json @@ -6033,6 +6033,85 @@ } } } + }, + "/GovNotifyMessage/sendsms": { + "post": { + "tags": [ + "SendSms" + ], + "summary": "Send an SMS.", + "required": [ "mobileNumber", "templateId" ], + "requestBody": { + "description": "The Sends an SMS using the UK Gov.Notify service.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SendSmsRequest" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/SendSmsRequest" + } + }, + "application/*+json": { + "schema": { + "$ref": "#/components/schemas/SendSmsRequest" + } + } + } + }, + "responses": { + "200": { + "description": "SMS successfully sent." + }, + "400": { + "description": "Bad request, invalid input." + }, + "500": { + "description": "Internal server error." + } + } + } + }, + "/GovNotifyMessage/sendemail": { + "post": { + "tags": [ + "SendEmail" + ], + "summary": "Send an Email.", + "requestBody": { + "description": "Sends an email using the UK Gov.Notify service.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SendEmailRequest" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/SendEmailRequest" + } + }, + "application/*+json": { + "schema": { + "$ref": "#/components/schemas/SendEmailRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Email successfully sent." + }, + "400": { + "description": "Bad request, invalid input." + }, + "500": { + "description": "Internal server error." + } + } + } } }, "components": { @@ -14138,6 +14217,51 @@ } }, "additionalProperties": false + }, + "SendSmsRequest": { + "type": "object", + "required": [ "mobileNumber", "templateId" ], + "properties": { + "mobileNumber": { + "type": "string", + "nullable": false, + "description": "The recipient's mobile number." + }, + "templateId": { + "type": "string", + "nullable": false, + "description": "The ID of the template to be used for the email." + }, + "personalisation": { + "type": "object", + "additionalProperties:": { + "type": "string" + }, + "description": "Key-value pairs for personalising the sms template." + } + } + }, + "SendEmailRequest": { + "type": "object", + "properties": { + "emailAddress": { + "type": "string", + "nullable": false, + "description": "The recipient's email address." + }, + "templateId": { + "type": "string", + "nullable": false, + "description": "The ID of the template to be used for the email." + }, + "personalisation": { + "type": "object", + "additionalProperties:": { + "type": "string" + }, + "description": "Key-value pairs for personalising the email template." + } + } } }, "securitySchemes": { diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/appsettings.json b/OpenAPI/LearningHub.Nhs.OpenApi/appsettings.json index 92f23e650..56c507cff 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi/appsettings.json +++ b/OpenAPI/LearningHub.Nhs.OpenApi/appsettings.json @@ -84,5 +84,8 @@ "ResponseType": "code id_token", "AuthSecret": "", "AuthTimeout": 20 + }, + "GovNotify": { + "GovNotifyApiKey": "" } } From b2cdaf8c81b3a85689ec241e2cba4c6a90e65ccc Mon Sep 17 00:00:00 2001 From: Arunima George Date: Mon, 28 Apr 2025 16:16:58 +0100 Subject: [PATCH 02/16] TD-5477: Change in folder structure --- .gitignore | 2 + LearningHub.Nhs.WebUI.sln | 48 ++++++++-- ...ngHub.Nhs.MessageQueueing.Database.sqlproj | 61 ++++++++++++ ....Nhs.MessageQueueing.Database.sqlproj.user | 3 + .../Entities/EmailQueue.cs | 82 ++++++++++++++++ .../EntityFramework/MessageQueueDbContext.cs | 25 +++++ .../LearningHub.Nhs.MessageQueueing.csproj | 13 +++ .../Repositories/EmailQueueRepository.cs | 94 +++++++++++++++++++ .../Repositories/IEmailQueueRepository.cs | 43 +++++++++ .../Interfaces/IGovNotifyService.cs | 0 .../LearningHub.Nhs.MessagingService.csproj | 0 .../Model/MessagingServiceModel.cs | 0 .../Model/SendEmailRequest.cs | 0 .../Model/SendSmsRequest.cs | 0 .../Services/GovNotifyService.cs | 0 .../Startup.cs | 0 .../LearningHub.NHS.OpenAPI.csproj | 4 +- 17 files changed, 363 insertions(+), 12 deletions(-) create mode 100644 MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/LearningHub.Nhs.MessageQueueing.Database.sqlproj create mode 100644 MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/LearningHub.Nhs.MessageQueueing.Database.sqlproj.user create mode 100644 MessageQueueing/LearningHub.Nhs.MessageQueueing/Entities/EmailQueue.cs create mode 100644 MessageQueueing/LearningHub.Nhs.MessageQueueing/EntityFramework/MessageQueueDbContext.cs create mode 100644 MessageQueueing/LearningHub.Nhs.MessageQueueing/LearningHub.Nhs.MessageQueueing.csproj create mode 100644 MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/EmailQueueRepository.cs create mode 100644 MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/IEmailQueueRepository.cs rename {LearningHub.Nhs.MessagingService => MessagingService/LearningHub.Nhs.MessagingService}/Interfaces/IGovNotifyService.cs (100%) rename {LearningHub.Nhs.MessagingService => MessagingService/LearningHub.Nhs.MessagingService}/LearningHub.Nhs.MessagingService.csproj (100%) rename {LearningHub.Nhs.MessagingService => MessagingService/LearningHub.Nhs.MessagingService}/Model/MessagingServiceModel.cs (100%) rename {LearningHub.Nhs.MessagingService => MessagingService/LearningHub.Nhs.MessagingService}/Model/SendEmailRequest.cs (100%) rename {LearningHub.Nhs.MessagingService => MessagingService/LearningHub.Nhs.MessagingService}/Model/SendSmsRequest.cs (100%) rename {LearningHub.Nhs.MessagingService => MessagingService/LearningHub.Nhs.MessagingService}/Services/GovNotifyService.cs (100%) rename {LearningHub.Nhs.MessagingService => MessagingService/LearningHub.Nhs.MessagingService}/Startup.cs (100%) diff --git a/.gitignore b/.gitignore index fcd06e014..5bc784140 100644 --- a/.gitignore +++ b/.gitignore @@ -53,3 +53,5 @@ obj /AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj.user /WebAPI/LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj.user /ReportAPI/LearningHub.Nhs.ReportApi/web.config +/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/LearningHub.Nhs.MessageQueueing.Database.dbmdl +/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/LearningHub.Nhs.MessageQueueing.Database.jfm \ No newline at end of file diff --git a/LearningHub.Nhs.WebUI.sln b/LearningHub.Nhs.WebUI.sln index e4ca88071..43f5211d5 100644 --- a/LearningHub.Nhs.WebUI.sln +++ b/LearningHub.Nhs.WebUI.sln @@ -83,7 +83,13 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LearningHub.Nhs.WebUI.Autom EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MessagingService", "MessagingService", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LearningHub.Nhs.MessagingService", "LearningHub.Nhs.MessagingService\LearningHub.Nhs.MessagingService.csproj", "{713B0099-60E3-4D28-980F-448FC68BC7EE}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MessageQueueing", "MessageQueueing", "{FC592E2B-861F-4C9A-BD1A-95CB97D36285}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LearningHub.Nhs.MessageQueueing", "MessageQueueing\LearningHub.Nhs.MessageQueueing\LearningHub.Nhs.MessageQueueing.csproj", "{534A145F-1FE4-B601-48FF-979744373E4B}" +EndProject +Project("{00D1A9C2-B5F0-4AF3-8072-F6C62B433612}") = "LearningHub.Nhs.MessageQueueing.Database", "MessageQueueing\LearningHub.Nhs.MessageQueueing.Database\LearningHub.Nhs.MessageQueueing.Database.sqlproj", "{AFC1A740-BBA1-44BC-8A52-A65D2E506E69}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LearningHub.Nhs.MessagingService", "MessagingService\LearningHub.Nhs.MessagingService\LearningHub.Nhs.MessagingService.csproj", "{CCB52C7C-47B6-1AE7-7578-7A26B3FFEB71}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -349,14 +355,34 @@ Global {A84EC50B-2B01-4819-A2B1-BD867B7595CA}.Release|Any CPU.Build.0 = Release|Any CPU {A84EC50B-2B01-4819-A2B1-BD867B7595CA}.Release|x64.ActiveCfg = Release|Any CPU {A84EC50B-2B01-4819-A2B1-BD867B7595CA}.Release|x64.Build.0 = Release|Any CPU - {713B0099-60E3-4D28-980F-448FC68BC7EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {713B0099-60E3-4D28-980F-448FC68BC7EE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {713B0099-60E3-4D28-980F-448FC68BC7EE}.Debug|x64.ActiveCfg = Debug|Any CPU - {713B0099-60E3-4D28-980F-448FC68BC7EE}.Debug|x64.Build.0 = Debug|Any CPU - {713B0099-60E3-4D28-980F-448FC68BC7EE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {713B0099-60E3-4D28-980F-448FC68BC7EE}.Release|Any CPU.Build.0 = Release|Any CPU - {713B0099-60E3-4D28-980F-448FC68BC7EE}.Release|x64.ActiveCfg = Release|Any CPU - {713B0099-60E3-4D28-980F-448FC68BC7EE}.Release|x64.Build.0 = Release|Any CPU + {534A145F-1FE4-B601-48FF-979744373E4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {534A145F-1FE4-B601-48FF-979744373E4B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {534A145F-1FE4-B601-48FF-979744373E4B}.Debug|x64.ActiveCfg = Debug|Any CPU + {534A145F-1FE4-B601-48FF-979744373E4B}.Debug|x64.Build.0 = Debug|Any CPU + {534A145F-1FE4-B601-48FF-979744373E4B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {534A145F-1FE4-B601-48FF-979744373E4B}.Release|Any CPU.Build.0 = Release|Any CPU + {534A145F-1FE4-B601-48FF-979744373E4B}.Release|x64.ActiveCfg = Release|Any CPU + {534A145F-1FE4-B601-48FF-979744373E4B}.Release|x64.Build.0 = Release|Any CPU + {AFC1A740-BBA1-44BC-8A52-A65D2E506E69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AFC1A740-BBA1-44BC-8A52-A65D2E506E69}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AFC1A740-BBA1-44BC-8A52-A65D2E506E69}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {AFC1A740-BBA1-44BC-8A52-A65D2E506E69}.Debug|x64.ActiveCfg = Debug|Any CPU + {AFC1A740-BBA1-44BC-8A52-A65D2E506E69}.Debug|x64.Build.0 = Debug|Any CPU + {AFC1A740-BBA1-44BC-8A52-A65D2E506E69}.Debug|x64.Deploy.0 = Debug|Any CPU + {AFC1A740-BBA1-44BC-8A52-A65D2E506E69}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AFC1A740-BBA1-44BC-8A52-A65D2E506E69}.Release|Any CPU.Build.0 = Release|Any CPU + {AFC1A740-BBA1-44BC-8A52-A65D2E506E69}.Release|Any CPU.Deploy.0 = Release|Any CPU + {AFC1A740-BBA1-44BC-8A52-A65D2E506E69}.Release|x64.ActiveCfg = Release|Any CPU + {AFC1A740-BBA1-44BC-8A52-A65D2E506E69}.Release|x64.Build.0 = Release|Any CPU + {AFC1A740-BBA1-44BC-8A52-A65D2E506E69}.Release|x64.Deploy.0 = Release|Any CPU + {CCB52C7C-47B6-1AE7-7578-7A26B3FFEB71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CCB52C7C-47B6-1AE7-7578-7A26B3FFEB71}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CCB52C7C-47B6-1AE7-7578-7A26B3FFEB71}.Debug|x64.ActiveCfg = Debug|Any CPU + {CCB52C7C-47B6-1AE7-7578-7A26B3FFEB71}.Debug|x64.Build.0 = Debug|Any CPU + {CCB52C7C-47B6-1AE7-7578-7A26B3FFEB71}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CCB52C7C-47B6-1AE7-7578-7A26B3FFEB71}.Release|Any CPU.Build.0 = Release|Any CPU + {CCB52C7C-47B6-1AE7-7578-7A26B3FFEB71}.Release|x64.ActiveCfg = Release|Any CPU + {CCB52C7C-47B6-1AE7-7578-7A26B3FFEB71}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -392,7 +418,9 @@ Global {E585A74A-F358-4446-B10E-0FF07B4FF601} = {A4209011-1740-4902-B889-2F2FAF98383F} {AAC8306E-1DEB-460D-84C7-40166D189B88} = {A4209011-1740-4902-B889-2F2FAF98383F} {6167F037-166C-4C5A-81BE-55618E77D4E8} = {A4209011-1740-4902-B889-2F2FAF98383F} - {713B0099-60E3-4D28-980F-448FC68BC7EE} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} + {534A145F-1FE4-B601-48FF-979744373E4B} = {FC592E2B-861F-4C9A-BD1A-95CB97D36285} + {AFC1A740-BBA1-44BC-8A52-A65D2E506E69} = {FC592E2B-861F-4C9A-BD1A-95CB97D36285} + {CCB52C7C-47B6-1AE7-7578-7A26B3FFEB71} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {1ECA38C8-7C69-4DE6-8293-852C603F4217} diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/LearningHub.Nhs.MessageQueueing.Database.sqlproj b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/LearningHub.Nhs.MessageQueueing.Database.sqlproj new file mode 100644 index 000000000..4af759781 --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/LearningHub.Nhs.MessageQueueing.Database.sqlproj @@ -0,0 +1,61 @@ + + + + Debug + AnyCPU + LearningHub.Nhs.MessageQueueing.Database + 2.0 + 4.1 + {afc1a740-bba1-44bc-8a52-a65d2e506e69} + Microsoft.Data.Tools.Schema.Sql.Sql160DatabaseSchemaProvider + Database + + + LearningHub.Nhs.MessageQueueing.Database + LearningHub.Nhs.MessageQueueing.Database + 1033, CI + BySchemaAndSchemaType + True + v4.7.2 + CS + Properties + False + True + True + + + bin\Release\ + $(MSBuildProjectName).sql + False + pdbonly + true + false + true + prompt + 4 + + + bin\Debug\ + $(MSBuildProjectName).sql + false + true + full + false + true + true + prompt + 4 + + + 11.0 + + True + 11.0 + + + + + + + + \ No newline at end of file diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/LearningHub.Nhs.MessageQueueing.Database.sqlproj.user b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/LearningHub.Nhs.MessageQueueing.Database.sqlproj.user new file mode 100644 index 000000000..0b07de1b2 --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/LearningHub.Nhs.MessageQueueing.Database.sqlproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing/Entities/EmailQueue.cs b/MessageQueueing/LearningHub.Nhs.MessageQueueing/Entities/EmailQueue.cs new file mode 100644 index 000000000..dda38331b --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing/Entities/EmailQueue.cs @@ -0,0 +1,82 @@ +namespace LearningHub.Nhs.MessageQueueing.Entities +{ + using System; + using System.ComponentModel.DataAnnotations; + + /// + /// The Email Queue. + /// + public class EmailQueue + { + /// + /// Gets or sets the id. + /// + [Key] + public Guid Id { get; set; } + + /// + /// Gets or sets the Recipient. + /// + public string Recipient { get; set; } + + /// + /// Gets or sets the Subject. + /// + public string Subject { get; set; } + + /// + /// Gets or sets the Body. + /// + public string? Body { get; set; } + + /// + /// Gets or sets the TemplateId. + /// + public string TemplateId { get; set; } + + /// + /// Gets or sets the Personalisation. + /// + public string? Personalisation { get; set; } + + /// + /// Gets or sets the Status. + /// + public string Status { get; set; } + + /// + /// Gets or sets the NotificationId. + /// + public string? NotificationId { get; set; } + + /// + /// Gets or sets the RetryCount. + /// + public int RetryCount { get; set; } + + /// + /// Gets or sets the CreatedAt. + /// + public DateTimeOffset CreatedAt { get; set; } + + /// + /// Gets or sets the DeliverAfter. + /// + public DateTimeOffset? DeliverAfter { get; set; } + + /// + /// Gets or sets the SentAt. + /// + public DateTimeOffset? SentAt { get; set; } + + /// + /// Gets or sets the LastAttemptAt. + /// + public DateTimeOffset? LastAttemptAt { get; set; } + + /// + /// Gets or sets the ErrorMessage. + /// + public string? ErrorMessage { get; set; } + } +} diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing/EntityFramework/MessageQueueDbContext.cs b/MessageQueueing/LearningHub.Nhs.MessageQueueing/EntityFramework/MessageQueueDbContext.cs new file mode 100644 index 000000000..f0292d9ab --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing/EntityFramework/MessageQueueDbContext.cs @@ -0,0 +1,25 @@ +namespace LearningHub.Nhs.MessageQueueing.EntityFramework +{ + using LearningHub.Nhs.MessageQueueing.Entities; + using Microsoft.EntityFrameworkCore; + + /// + /// The Message Queue Db Context. + /// + public class MessageQueueDbContext : DbContext + { + /// + /// Initializes a new instance of the class. + /// + /// The options. + public MessageQueueDbContext(DbContextOptions options) + : base(options) + { + } + + /// + /// Gets or sets the EmailQueues. + /// + public virtual DbSet EmailQueues { get; set; } + } +} diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing/LearningHub.Nhs.MessageQueueing.csproj b/MessageQueueing/LearningHub.Nhs.MessageQueueing/LearningHub.Nhs.MessageQueueing.csproj new file mode 100644 index 000000000..70aef10b7 --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing/LearningHub.Nhs.MessageQueueing.csproj @@ -0,0 +1,13 @@ + + + + net8.0 + enable + true + + + + + + + diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/EmailQueueRepository.cs b/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/EmailQueueRepository.cs new file mode 100644 index 000000000..8371e58dd --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/EmailQueueRepository.cs @@ -0,0 +1,94 @@ +namespace LearningHub.Nhs.MessageQueueing.Repositories +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using LearningHub.Nhs.MessageQueueing.Entities; + using LearningHub.Nhs.MessageQueueing.EntityFramework; + using Microsoft.EntityFrameworkCore; + + /// + /// The EmailQueueRepository. + /// + public class EmailQueueRepository : IEmailQueueRepository + { + private readonly MessageQueueDbContext dbContext; + + /// + /// Initializes a new instance of the class. + /// + /// The context. + public EmailQueueRepository(MessageQueueDbContext dbContext) + { + this.dbContext = dbContext; + } + + /// + /// The QueueEmailsAsync. + /// + /// The emails. + /// The . + public async Task QueueEmailsAsync(IEnumerable emails) + { + await this.dbContext.EmailQueues.AddRangeAsync(emails); + await this.dbContext.SaveChangesAsync(); + } + + /// + /// The GetPendingEmailsAsync. + /// + /// The . + public async Task> GetPendingEmailsAsync() + { + return await this.dbContext.EmailQueues + .Where(e => e.Status == "Pending" && e.RetryCount < 3) + .OrderBy(e => e.CreatedAt) + .ToListAsync(); + } + + /// + /// The UpdateEmailStatusAsync. + /// + /// The Id. + /// The status. + /// The error message. + /// The . + public async Task UpdateEmailStatusAsync(Guid id, string status, string errorMessage = null) + { + var email = await this.dbContext.EmailQueues.FindAsync(id); + if (email != null) + { + email.Status = status; + email.ErrorMessage = errorMessage; + email.SentAt = status == "Sent" ? DateTime.UtcNow : null; + + await this.dbContext.SaveChangesAsync(); + } + } + + /// + /// The IncrementRetryAsync. + /// + /// The id. + /// The errorMessage. + /// The . + public async Task IncrementRetryAsync(Guid id, string errorMessage) + { + var email = await this.dbContext.EmailQueues.FindAsync(id); + if (email != null) + { + email.RetryCount++; + email.LastAttemptAt = DateTime.UtcNow; + email.ErrorMessage = errorMessage; + + if (email.RetryCount >= 3) + { + email.Status = "Failed"; + } + + await this.dbContext.SaveChangesAsync(); + } + } + } +} diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/IEmailQueueRepository.cs b/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/IEmailQueueRepository.cs new file mode 100644 index 000000000..11991348f --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/IEmailQueueRepository.cs @@ -0,0 +1,43 @@ +namespace LearningHub.Nhs.MessageQueueing.Repositories +{ + using System; + using System.Collections.Generic; + using System.Threading.Tasks; + using LearningHub.Nhs.MessageQueueing.Entities; + + /// + /// The IEmailQueueRepository class. + /// + public interface IEmailQueueRepository + { + /// + /// The QueueEmailsAsync. + /// + /// The emails list. + /// The . + Task QueueEmailsAsync(IEnumerable emails); + + /// + /// The GetPendingEmailsAsync. + /// + /// The . + Task> GetPendingEmailsAsync(); + + /// + /// The UpdateEmailStatusAsync. + /// + /// Id. + /// status. + /// Error Message. + /// The . + Task UpdateEmailStatusAsync(Guid id, string status, string errorMessage); + + /// + /// The IncrementRetryAsync. + /// + /// Id. + /// error message. + /// The . + Task IncrementRetryAsync(Guid id, string errorMessage); + } +} diff --git a/LearningHub.Nhs.MessagingService/Interfaces/IGovNotifyService.cs b/MessagingService/LearningHub.Nhs.MessagingService/Interfaces/IGovNotifyService.cs similarity index 100% rename from LearningHub.Nhs.MessagingService/Interfaces/IGovNotifyService.cs rename to MessagingService/LearningHub.Nhs.MessagingService/Interfaces/IGovNotifyService.cs diff --git a/LearningHub.Nhs.MessagingService/LearningHub.Nhs.MessagingService.csproj b/MessagingService/LearningHub.Nhs.MessagingService/LearningHub.Nhs.MessagingService.csproj similarity index 100% rename from LearningHub.Nhs.MessagingService/LearningHub.Nhs.MessagingService.csproj rename to MessagingService/LearningHub.Nhs.MessagingService/LearningHub.Nhs.MessagingService.csproj diff --git a/LearningHub.Nhs.MessagingService/Model/MessagingServiceModel.cs b/MessagingService/LearningHub.Nhs.MessagingService/Model/MessagingServiceModel.cs similarity index 100% rename from LearningHub.Nhs.MessagingService/Model/MessagingServiceModel.cs rename to MessagingService/LearningHub.Nhs.MessagingService/Model/MessagingServiceModel.cs diff --git a/LearningHub.Nhs.MessagingService/Model/SendEmailRequest.cs b/MessagingService/LearningHub.Nhs.MessagingService/Model/SendEmailRequest.cs similarity index 100% rename from LearningHub.Nhs.MessagingService/Model/SendEmailRequest.cs rename to MessagingService/LearningHub.Nhs.MessagingService/Model/SendEmailRequest.cs diff --git a/LearningHub.Nhs.MessagingService/Model/SendSmsRequest.cs b/MessagingService/LearningHub.Nhs.MessagingService/Model/SendSmsRequest.cs similarity index 100% rename from LearningHub.Nhs.MessagingService/Model/SendSmsRequest.cs rename to MessagingService/LearningHub.Nhs.MessagingService/Model/SendSmsRequest.cs diff --git a/LearningHub.Nhs.MessagingService/Services/GovNotifyService.cs b/MessagingService/LearningHub.Nhs.MessagingService/Services/GovNotifyService.cs similarity index 100% rename from LearningHub.Nhs.MessagingService/Services/GovNotifyService.cs rename to MessagingService/LearningHub.Nhs.MessagingService/Services/GovNotifyService.cs diff --git a/LearningHub.Nhs.MessagingService/Startup.cs b/MessagingService/LearningHub.Nhs.MessagingService/Startup.cs similarity index 100% rename from LearningHub.Nhs.MessagingService/Startup.cs rename to MessagingService/LearningHub.Nhs.MessagingService/Startup.cs diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj b/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj index 6ed354944..56f52c05e 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj @@ -1,4 +1,4 @@ - + enable @@ -31,7 +31,7 @@ - + From b6e49b37703b7f22418f2fffc77eaf7d50f854b1 Mon Sep 17 00:00:00 2001 From: Arunima George Date: Tue, 27 May 2025 13:17:48 +0100 Subject: [PATCH 03/16] TD-5477: Create an email queue processing system. --- .../LearningHub.Nhs.AdminUI.csproj | 2 +- .../LearningHub.Nhs.WebUI.csproj | 2 +- ...ngHub.Nhs.MessageQueueing.Database.sqlproj | 20 +++ .../Post-Deploy/Scripts/RequestStatusData.sql | 6 + .../Post-Deploy/Scripts/RequestTypeData.sql | 6 + .../Stored Procedures/CreateQueueRequests.sql | 10 ++ .../Stored Procedures/GetQueueRequests.sql | 10 ++ .../MessageDeliveryFailed.sql | 14 +++ .../MessageDeliverySuccess.sql | 16 +++ .../SaveFailedSingleEmail.sql | 11 ++ .../Tables/QueueRequests.sql | 34 ++++++ .../Tables/RequestStatus.sql | 9 ++ .../Tables/RequestType.sql | 9 ++ .../QueueRequestTableType.sql | 7 ++ .../Entities/EmailQueue.cs | 82 ------------- .../EntityFramework/MessageQueueDbContext.cs | 26 +++- .../MessageQueueDbContextOptions.cs | 24 ++++ .../Helpers/DataTableBuilder.cs | 34 ++++++ .../LearningHub.Nhs.MessageQueueing.csproj | 2 + .../Repositories/EmailQueueRepository.cs | 94 --------------- .../Repositories/IEmailQueueRepository.cs | 43 ------- .../Repositories/IMessageQueueRepository.cs | 47 ++++++++ .../Repositories/MessageQueueRepository.cs | 90 ++++++++++++++ .../Startup.cs | 32 +++++ .../Interfaces/IGovNotifyService.cs | 5 +- .../LearningHub.Nhs.MessagingService.csproj | 1 + .../MessagingServiceOptions.cs} | 6 +- .../Model/SendEmailRequest.cs | 28 ----- .../Model/SendSmsRequest.cs | 28 ----- .../Services/GovNotifyService.cs | 114 +++++++++++++----- .../Startup.cs | 2 +- .../LearningHub.Nhs.OpenApi.Models.csproj | 2 +- ...gHub.Nhs.OpenApi.Services.Interface.csproj | 2 +- .../LearningHub.Nhs.OpenApi.Services.csproj | 2 +- .../GovNotifyMessagingController.cs | 107 ++++++++++++++-- .../LearningHub.NHS.OpenAPI.csproj | 1 + OpenAPI/LearningHub.Nhs.OpenApi/Startup.cs | 4 + .../SwaggerDefinitions/v1.3.0.json | 113 ++++++++++++++--- .../LearningHub.Nhs.OpenApi/appsettings.json | 7 ++ ...ub.Nhs.ReportApi.Services.Interface.csproj | 2 +- ...ub.Nhs.ReportApi.Services.UnitTests.csproj | 2 +- .../LearningHub.Nhs.ReportApi.Services.csproj | 2 +- .../LearningHub.Nhs.ReportApi.Shared.csproj | 2 +- .../LearningHub.Nhs.ReportApi.csproj | 2 +- .../LearningHub.Nhs.Api.csproj | 2 +- .../LearningHub.Nhs.Api.Shared.csproj | 2 +- .../LearningHub.Nhs.Api.UnitTests.csproj | 2 +- ...earningHub.Nhs.Repository.Interface.csproj | 2 +- .../LearningHub.Nhs.Repository.csproj | 2 +- .../LearningHub.Nhs.Services.Interface.csproj | 2 +- .../LearningHub.Nhs.Services.UnitTests.csproj | 2 +- .../LearningHub.Nhs.Services.csproj | 2 +- ...earningHub.Nhs.Migration.ConsoleApp.csproj | 2 +- ...LearningHub.Nhs.Migration.Interface.csproj | 2 +- .../LearningHub.Nhs.Migration.Models.csproj | 2 +- ...ub.Nhs.Migration.Staging.Repository.csproj | 2 +- ...LearningHub.Nhs.Migration.UnitTests.csproj | 2 +- .../LearningHub.Nhs.Migration.csproj | 2 +- 58 files changed, 719 insertions(+), 371 deletions(-) create mode 100644 MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Scripts/Post-Deploy/Scripts/RequestStatusData.sql create mode 100644 MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Scripts/Post-Deploy/Scripts/RequestTypeData.sql create mode 100644 MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/CreateQueueRequests.sql create mode 100644 MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/GetQueueRequests.sql create mode 100644 MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/MessageDeliveryFailed.sql create mode 100644 MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/MessageDeliverySuccess.sql create mode 100644 MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/SaveFailedSingleEmail.sql create mode 100644 MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Tables/QueueRequests.sql create mode 100644 MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Tables/RequestStatus.sql create mode 100644 MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Tables/RequestType.sql create mode 100644 MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/User-Defined Table Types/QueueRequestTableType.sql delete mode 100644 MessageQueueing/LearningHub.Nhs.MessageQueueing/Entities/EmailQueue.cs create mode 100644 MessageQueueing/LearningHub.Nhs.MessageQueueing/EntityFramework/MessageQueueDbContextOptions.cs create mode 100644 MessageQueueing/LearningHub.Nhs.MessageQueueing/Helpers/DataTableBuilder.cs delete mode 100644 MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/EmailQueueRepository.cs delete mode 100644 MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/IEmailQueueRepository.cs create mode 100644 MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/IMessageQueueRepository.cs create mode 100644 MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/MessageQueueRepository.cs create mode 100644 MessageQueueing/LearningHub.Nhs.MessageQueueing/Startup.cs rename MessagingService/LearningHub.Nhs.MessagingService/{Model/MessagingServiceModel.cs => MessagingOptions/MessagingServiceOptions.cs} (80%) delete mode 100644 MessagingService/LearningHub.Nhs.MessagingService/Model/SendEmailRequest.cs delete mode 100644 MessagingService/LearningHub.Nhs.MessagingService/Model/SendSmsRequest.cs diff --git a/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj b/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj index eba6b6ffa..2038ce016 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj +++ b/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj @@ -89,7 +89,7 @@ - + diff --git a/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj b/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj index 1b4ac83d1..fa0dca0f8 100644 --- a/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj +++ b/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj @@ -113,7 +113,7 @@ - + diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/LearningHub.Nhs.MessageQueueing.Database.sqlproj b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/LearningHub.Nhs.MessageQueueing.Database.sqlproj index 4af759781..79c159525 100644 --- a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/LearningHub.Nhs.MessageQueueing.Database.sqlproj +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/LearningHub.Nhs.MessageQueueing.Database.sqlproj @@ -57,5 +57,25 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Scripts/Post-Deploy/Scripts/RequestStatusData.sql b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Scripts/Post-Deploy/Scripts/RequestStatusData.sql new file mode 100644 index 000000000..d09b31f81 --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Scripts/Post-Deploy/Scripts/RequestStatusData.sql @@ -0,0 +1,6 @@ +INSERT [dbo].[RequestStatus] ([Id], [RequestStatus]) VALUES (1, N'Pending') +GO +INSERT [dbo].[RequestStatus] ([Id], [RequestStatus]) VALUES (2, N'Sent') +GO +INSERT [dbo].[RequestStatus] ([Id], [RequestStatus]) VALUES (3, N'Failed') +GO \ No newline at end of file diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Scripts/Post-Deploy/Scripts/RequestTypeData.sql b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Scripts/Post-Deploy/Scripts/RequestTypeData.sql new file mode 100644 index 000000000..a933ca65a --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Scripts/Post-Deploy/Scripts/RequestTypeData.sql @@ -0,0 +1,6 @@ +INSERT [dbo].[RequestType] ([Id], [RequestType]) VALUES (1, N'Email') +GO +INSERT [dbo].[RequestType] ([Id], [RequestType]) VALUES (2, N'SMS') +GO +INSERT [dbo].[RequestType] ([Id], [RequestType]) VALUES (3, N'SingleEmail') +GO \ No newline at end of file diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/CreateQueueRequests.sql b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/CreateQueueRequests.sql new file mode 100644 index 000000000..b9cd5d3d1 --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/CreateQueueRequests.sql @@ -0,0 +1,10 @@ +Create PROCEDURE [dbo].[CreateQueueRequests] + @QueueRequests dbo.QueueRequestTableType READONLY +AS +BEGIN + + INSERT INTO QueueRequests (RequestTypeId, Recipient, TemplateId, Personalisation, Status, RetryCount, CreatedAt, DeliverAfter) + SELECT 1, Recipient, TemplateId, Personalisation, 1, 0, SYSDATETIMEOFFSET(), DeliverAfter + FROM @QueueRequests; +END +GO diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/GetQueueRequests.sql b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/GetQueueRequests.sql new file mode 100644 index 000000000..a23cd61a6 --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/GetQueueRequests.sql @@ -0,0 +1,10 @@ +CREATE PROCEDURE [dbo].[GetQueueRequests] +AS +BEGIN + + select Id,Recipient,TemplateId,Personalisation,Status,RetryCount + from dbo.QueueRequests +where RequestTypeId = 1 and Status in (1,3) and RetryCount < 3 and (DeliverAfter is null or DeliverAfter <= SYSDATETIMEOFFSET()) + +END +GO \ No newline at end of file diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/MessageDeliveryFailed.sql b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/MessageDeliveryFailed.sql new file mode 100644 index 000000000..8c6b6b606 --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/MessageDeliveryFailed.sql @@ -0,0 +1,14 @@ +CREATE PROCEDURE [dbo].[MessageDeliveryFailed] + @Id int, + @ErrorMessage nvarchar(max) +AS +BEGIN + UPDATE [dbo].[QueueRequests] + SET + Status = 3, + RetryCount = RetryCount + 1, + ErrorMessage = @ErrorMessage, + LastAttemptAt = SYSDATETIMEOFFSET() + where Id = @Id; +END +GO \ No newline at end of file diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/MessageDeliverySuccess.sql b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/MessageDeliverySuccess.sql new file mode 100644 index 000000000..73c18ebdd --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/MessageDeliverySuccess.sql @@ -0,0 +1,16 @@ +CREATE PROCEDURE [dbo].[MessageDeliverySuccess] + @Id int, + @NotificationId nvarchar(100) + +AS +BEGIN + UPDATE [dbo].[QueueRequests] + SET + Status = 2, + NotificationId = @NotificationId, + RetryCount = RetryCount + 1, + SentAt = SYSDATETIMEOFFSET(), + LastAttemptAt = SYSDATETIMEOFFSET() + where Id = @Id; +END +GO \ No newline at end of file diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/SaveFailedSingleEmail.sql b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/SaveFailedSingleEmail.sql new file mode 100644 index 000000000..e9b9a849e --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/SaveFailedSingleEmail.sql @@ -0,0 +1,11 @@ +CREATE PROCEDURE [dbo].[SaveFailedSingleEmail] + @Recipient nvarchar(255), + @TemplateId nvarchar(50), + @Personalisation nvarchar(max), + @ErrorMessage nvarchar(max) +AS +BEGIN + insert into [dbo].[QueueRequests] (RequestTypeId, Recipient, TemplateId, Personalisation, Status, CreatedAt, LastAttemptAt,ErrorMessage ) + values (3, @Recipient, @TemplateId, @Personalisation, 3, SYSDATETIMEOFFSET(), SYSDATETIMEOFFSET(), @ErrorMessage); +END +GO diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Tables/QueueRequests.sql b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Tables/QueueRequests.sql new file mode 100644 index 000000000..fad33bf9d --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Tables/QueueRequests.sql @@ -0,0 +1,34 @@ +CREATE TABLE [dbo].[QueueRequests]( + [Id] [int] IDENTITY(1,1) NOT NULL, + [RequestTypeId] [int] NOT NULL, + [Recipient] [nvarchar](255) NOT NULL, + [TemplateId] [nvarchar](50) NOT NULL, + [Personalisation] [nvarchar](max) NULL, + [Status] [int] NOT NULL, + [NotificationId] [nvarchar](100) NULL, + [RetryCount] [int] NULL, + [CreatedAt] [datetimeoffset](7) NOT NULL, + [DeliverAfter] [datetimeoffset](7) NULL, + [SentAt] [datetimeoffset](7) NULL, + [LastAttemptAt] [datetimeoffset](7) NULL, + [ErrorMessage] [nvarchar](max) NULL, + CONSTRAINT [PK_QueueRequests] PRIMARY KEY CLUSTERED +( + [Id] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY] +) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] +GO + +ALTER TABLE [dbo].[QueueRequests] WITH CHECK ADD CONSTRAINT [FK_QueueRequests_RequestStatus] FOREIGN KEY([Status]) +REFERENCES [dbo].[RequestStatus] ([Id]) +GO + +ALTER TABLE [dbo].[QueueRequests] CHECK CONSTRAINT [FK_QueueRequests_RequestStatus] +GO + +ALTER TABLE [dbo].[QueueRequests] WITH CHECK ADD CONSTRAINT [FK_QueueRequests_RequestType] FOREIGN KEY([RequestTypeId]) +REFERENCES [dbo].[RequestType] ([Id]) +GO + +ALTER TABLE [dbo].[QueueRequests] CHECK CONSTRAINT [FK_QueueRequests_RequestType] +GO \ No newline at end of file diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Tables/RequestStatus.sql b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Tables/RequestStatus.sql new file mode 100644 index 000000000..ce9918dc3 --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Tables/RequestStatus.sql @@ -0,0 +1,9 @@ +CREATE TABLE [dbo].[RequestStatus]( + [Id] [int] NOT NULL, + [RequestStatus] [nvarchar](20) NOT NULL, + CONSTRAINT [PK_RequestStatus] PRIMARY KEY CLUSTERED +( + [Id] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY] +) ON [PRIMARY] +GO \ No newline at end of file diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Tables/RequestType.sql b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Tables/RequestType.sql new file mode 100644 index 000000000..a9be6c049 --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Tables/RequestType.sql @@ -0,0 +1,9 @@ +CREATE TABLE [dbo].[RequestType]( + [Id] [int] NOT NULL, + [RequestType] [nvarchar](20) NOT NULL, + CONSTRAINT [PK_RequestType] PRIMARY KEY CLUSTERED +( + [Id] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY] +) ON [PRIMARY] +GO diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/User-Defined Table Types/QueueRequestTableType.sql b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/User-Defined Table Types/QueueRequestTableType.sql new file mode 100644 index 000000000..479676b6b --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/User-Defined Table Types/QueueRequestTableType.sql @@ -0,0 +1,7 @@ +CREATE TYPE [dbo].[QueueRequestTableType] AS TABLE( + [Recipient] [nvarchar](255) NOT NULL, + [TemplateId] [nvarchar](50) NOT NULL, + [Personalisation] [nvarchar](max) NULL, + [DeliverAfter] [datetimeoffset](7) NULL +) +GO diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing/Entities/EmailQueue.cs b/MessageQueueing/LearningHub.Nhs.MessageQueueing/Entities/EmailQueue.cs deleted file mode 100644 index dda38331b..000000000 --- a/MessageQueueing/LearningHub.Nhs.MessageQueueing/Entities/EmailQueue.cs +++ /dev/null @@ -1,82 +0,0 @@ -namespace LearningHub.Nhs.MessageQueueing.Entities -{ - using System; - using System.ComponentModel.DataAnnotations; - - /// - /// The Email Queue. - /// - public class EmailQueue - { - /// - /// Gets or sets the id. - /// - [Key] - public Guid Id { get; set; } - - /// - /// Gets or sets the Recipient. - /// - public string Recipient { get; set; } - - /// - /// Gets or sets the Subject. - /// - public string Subject { get; set; } - - /// - /// Gets or sets the Body. - /// - public string? Body { get; set; } - - /// - /// Gets or sets the TemplateId. - /// - public string TemplateId { get; set; } - - /// - /// Gets or sets the Personalisation. - /// - public string? Personalisation { get; set; } - - /// - /// Gets or sets the Status. - /// - public string Status { get; set; } - - /// - /// Gets or sets the NotificationId. - /// - public string? NotificationId { get; set; } - - /// - /// Gets or sets the RetryCount. - /// - public int RetryCount { get; set; } - - /// - /// Gets or sets the CreatedAt. - /// - public DateTimeOffset CreatedAt { get; set; } - - /// - /// Gets or sets the DeliverAfter. - /// - public DateTimeOffset? DeliverAfter { get; set; } - - /// - /// Gets or sets the SentAt. - /// - public DateTimeOffset? SentAt { get; set; } - - /// - /// Gets or sets the LastAttemptAt. - /// - public DateTimeOffset? LastAttemptAt { get; set; } - - /// - /// Gets or sets the ErrorMessage. - /// - public string? ErrorMessage { get; set; } - } -} diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing/EntityFramework/MessageQueueDbContext.cs b/MessageQueueing/LearningHub.Nhs.MessageQueueing/EntityFramework/MessageQueueDbContext.cs index f0292d9ab..5b392c8d6 100644 --- a/MessageQueueing/LearningHub.Nhs.MessageQueueing/EntityFramework/MessageQueueDbContext.cs +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing/EntityFramework/MessageQueueDbContext.cs @@ -1,6 +1,6 @@ namespace LearningHub.Nhs.MessageQueueing.EntityFramework { - using LearningHub.Nhs.MessageQueueing.Entities; + using LearningHub.Nhs.Models.GovNotifyMessaging; using Microsoft.EntityFrameworkCore; /// @@ -8,18 +8,34 @@ /// public class MessageQueueDbContext : DbContext { + /// + /// The options. + /// + private readonly MessageQueueDbContextOptions options; + /// /// Initializes a new instance of the class. /// /// The options. - public MessageQueueDbContext(DbContextOptions options) - : base(options) + public MessageQueueDbContext(MessageQueueDbContextOptions options) + : base(options.Options) { + this.options = options; } /// - /// Gets or sets the EmailQueues. + /// Gets the Options. + /// + public MessageQueueDbContextOptions Options + { + get { return this.options; } + } + + ////public virtual DbSet QueueRequests { get; set; } + + /// + /// Gets or sets the PendingMessageRequests. /// - public virtual DbSet EmailQueues { get; set; } + public virtual DbSet PendingMessageRequests { get; set; } } } diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing/EntityFramework/MessageQueueDbContextOptions.cs b/MessageQueueing/LearningHub.Nhs.MessageQueueing/EntityFramework/MessageQueueDbContextOptions.cs new file mode 100644 index 000000000..7a6f0d985 --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing/EntityFramework/MessageQueueDbContextOptions.cs @@ -0,0 +1,24 @@ +namespace LearningHub.Nhs.MessageQueueing.EntityFramework +{ + using Microsoft.EntityFrameworkCore; + + /// + /// The MessageQueueDbContextOptions. + /// + public class MessageQueueDbContextOptions + { + /// + /// Initializes a new instance of the class. + /// + /// The options. + public MessageQueueDbContextOptions(DbContextOptions options) + { + this.Options = options; + } + + /// + /// Gets the options. + /// + public DbContextOptions Options { get; } + } +} diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing/Helpers/DataTableBuilder.cs b/MessageQueueing/LearningHub.Nhs.MessageQueueing/Helpers/DataTableBuilder.cs new file mode 100644 index 000000000..f4e278b94 --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing/Helpers/DataTableBuilder.cs @@ -0,0 +1,34 @@ +namespace LearningHub.Nhs.MessageQueueing.Helpers +{ + using System; + using System.Collections.Generic; + using System.Data; + using LearningHub.Nhs.Models.Entities.GovNotifyMessaging; + + /// + /// DataTable Builder. + /// + public static class DataTableBuilder + { + /// + /// ToQueueRequestDataTable. + /// + /// The requests list. + /// The table. + public static DataTable ToQueueRequestDataTable(IEnumerable requests) + { + var table = new DataTable(); + table.Columns.Add("Recipient", typeof(string)); + table.Columns.Add("TemplateId", typeof(string)); + table.Columns.Add("Personalisation", typeof(string)); + table.Columns.Add("DeliverAfter", typeof(DateTimeOffset)); + + foreach (var req in requests) + { + table.Rows.Add(req.Recipient, req.TemplateId, req.Personalisation, req.DeliverAfter); + } + + return table; + } + } +} diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing/LearningHub.Nhs.MessageQueueing.csproj b/MessageQueueing/LearningHub.Nhs.MessageQueueing/LearningHub.Nhs.MessageQueueing.csproj index 70aef10b7..1d7e25a32 100644 --- a/MessageQueueing/LearningHub.Nhs.MessageQueueing/LearningHub.Nhs.MessageQueueing.csproj +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing/LearningHub.Nhs.MessageQueueing.csproj @@ -7,7 +7,9 @@ + + diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/EmailQueueRepository.cs b/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/EmailQueueRepository.cs deleted file mode 100644 index 8371e58dd..000000000 --- a/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/EmailQueueRepository.cs +++ /dev/null @@ -1,94 +0,0 @@ -namespace LearningHub.Nhs.MessageQueueing.Repositories -{ - using System; - using System.Collections.Generic; - using System.Linq; - using System.Threading.Tasks; - using LearningHub.Nhs.MessageQueueing.Entities; - using LearningHub.Nhs.MessageQueueing.EntityFramework; - using Microsoft.EntityFrameworkCore; - - /// - /// The EmailQueueRepository. - /// - public class EmailQueueRepository : IEmailQueueRepository - { - private readonly MessageQueueDbContext dbContext; - - /// - /// Initializes a new instance of the class. - /// - /// The context. - public EmailQueueRepository(MessageQueueDbContext dbContext) - { - this.dbContext = dbContext; - } - - /// - /// The QueueEmailsAsync. - /// - /// The emails. - /// The . - public async Task QueueEmailsAsync(IEnumerable emails) - { - await this.dbContext.EmailQueues.AddRangeAsync(emails); - await this.dbContext.SaveChangesAsync(); - } - - /// - /// The GetPendingEmailsAsync. - /// - /// The . - public async Task> GetPendingEmailsAsync() - { - return await this.dbContext.EmailQueues - .Where(e => e.Status == "Pending" && e.RetryCount < 3) - .OrderBy(e => e.CreatedAt) - .ToListAsync(); - } - - /// - /// The UpdateEmailStatusAsync. - /// - /// The Id. - /// The status. - /// The error message. - /// The . - public async Task UpdateEmailStatusAsync(Guid id, string status, string errorMessage = null) - { - var email = await this.dbContext.EmailQueues.FindAsync(id); - if (email != null) - { - email.Status = status; - email.ErrorMessage = errorMessage; - email.SentAt = status == "Sent" ? DateTime.UtcNow : null; - - await this.dbContext.SaveChangesAsync(); - } - } - - /// - /// The IncrementRetryAsync. - /// - /// The id. - /// The errorMessage. - /// The . - public async Task IncrementRetryAsync(Guid id, string errorMessage) - { - var email = await this.dbContext.EmailQueues.FindAsync(id); - if (email != null) - { - email.RetryCount++; - email.LastAttemptAt = DateTime.UtcNow; - email.ErrorMessage = errorMessage; - - if (email.RetryCount >= 3) - { - email.Status = "Failed"; - } - - await this.dbContext.SaveChangesAsync(); - } - } - } -} diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/IEmailQueueRepository.cs b/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/IEmailQueueRepository.cs deleted file mode 100644 index 11991348f..000000000 --- a/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/IEmailQueueRepository.cs +++ /dev/null @@ -1,43 +0,0 @@ -namespace LearningHub.Nhs.MessageQueueing.Repositories -{ - using System; - using System.Collections.Generic; - using System.Threading.Tasks; - using LearningHub.Nhs.MessageQueueing.Entities; - - /// - /// The IEmailQueueRepository class. - /// - public interface IEmailQueueRepository - { - /// - /// The QueueEmailsAsync. - /// - /// The emails list. - /// The . - Task QueueEmailsAsync(IEnumerable emails); - - /// - /// The GetPendingEmailsAsync. - /// - /// The . - Task> GetPendingEmailsAsync(); - - /// - /// The UpdateEmailStatusAsync. - /// - /// Id. - /// status. - /// Error Message. - /// The . - Task UpdateEmailStatusAsync(Guid id, string status, string errorMessage); - - /// - /// The IncrementRetryAsync. - /// - /// Id. - /// error message. - /// The . - Task IncrementRetryAsync(Guid id, string errorMessage); - } -} diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/IMessageQueueRepository.cs b/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/IMessageQueueRepository.cs new file mode 100644 index 000000000..110343012 --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/IMessageQueueRepository.cs @@ -0,0 +1,47 @@ +namespace LearningHub.Nhs.MessageQueueing.Repositories +{ + using System.Collections.Generic; + using System.Threading.Tasks; + using LearningHub.Nhs.Models.Entities.GovNotifyMessaging; + using LearningHub.Nhs.Models.GovNotifyMessaging; + + /// + /// The IEmailQueueRepository class. + /// + public interface IMessageQueueRepository + { + /// + /// The QueueMessagesAsync. + /// + /// The emails list. + /// The . + Task QueueMessagesAsync(IEnumerable emails); + + /// + /// The GetPendingEmailsAsync. + /// + /// The . + Task> GetPendingEmailsAsync(); + + /// + /// Marks a message as failed, or queues it for a retry. + /// + /// The response. + /// The . + Task MessageDeliveryFailed(GovNotifyResponse response); + + /// + /// Marks a message as send. + /// + /// The response. + /// The . + Task MessageDeliverySuccess(GovNotifyResponse response); + + /// + /// Save failed one-off email. + /// + /// The email request. + /// The . + Task SaveFailedSingleEmail(SingleEmailFailedRequest request); + } +} diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/MessageQueueRepository.cs b/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/MessageQueueRepository.cs new file mode 100644 index 000000000..8e5059bd6 --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/MessageQueueRepository.cs @@ -0,0 +1,90 @@ +namespace LearningHub.Nhs.MessageQueueing.Repositories +{ + using System.Collections.Generic; + using System.Data; + using System.Threading.Tasks; + using LearningHub.Nhs.MessageQueueing.EntityFramework; + using LearningHub.Nhs.MessageQueueing.Helpers; + using LearningHub.Nhs.Models.Entities.GovNotifyMessaging; + using LearningHub.Nhs.Models.GovNotifyMessaging; + using Microsoft.Data.SqlClient; + using Microsoft.EntityFrameworkCore; + + /// + /// The MessageQueueRepository. + /// + public class MessageQueueRepository : IMessageQueueRepository + { + private readonly MessageQueueDbContext dbContext; + + /// + /// Initializes a new instance of the class. + /// + /// The context. + public MessageQueueRepository(MessageQueueDbContext dbContext) + { + this.dbContext = dbContext; + } + + /// + /// The QueueMessagesAsync. + /// + /// The queue requests. + /// The . + public async Task QueueMessagesAsync(IEnumerable requests) + { + var dataTable = DataTableBuilder.ToQueueRequestDataTable(requests); + var param0 = new SqlParameter("@p0", SqlDbType.Structured) { Value = dataTable, TypeName = "dbo.QueueRequestTableType" }; + await this.dbContext.Database.ExecuteSqlRawAsync("dbo.CreateQueueRequests @p0", param0); + } + + /// + /// The GetPendingEmailsAsync. + /// + /// The . + public async Task> GetPendingEmailsAsync() + { + var result = await this.dbContext.PendingMessageRequests.FromSqlRaw("[dbo].[GetQueueRequests]") + .AsNoTracking().ToListAsync(); + return result; + } + + /// + /// The Update Email request as success. + /// + /// Th response. + /// The . + public async Task MessageDeliverySuccess(GovNotifyResponse response) + { + var param0 = new SqlParameter("@p0", SqlDbType.Int) { Value = response.Id }; + var param1 = new SqlParameter("@p1", SqlDbType.NVarChar) { Value = response.NotificationId }; + await this.dbContext.Database.ExecuteSqlRawAsync("dbo.MessageDeliverySuccess @p0, @p1", param0, param1); + } + + /// + /// The Update Email request as failed. + /// + /// Th response. + /// The . + public async Task MessageDeliveryFailed(GovNotifyResponse response) + { + var param0 = new SqlParameter("@p0", SqlDbType.Int) { Value = response.Id }; + var param1 = new SqlParameter("@p1", SqlDbType.NVarChar) { Value = response.ErrorMessage }; + await this.dbContext.Database.ExecuteSqlRawAsync("dbo.MessageDeliveryFailed @p0, @p1", param0, param1); + } + + /// + /// The Save failed Single Emails. + /// + /// The request. + /// The . + public async Task SaveFailedSingleEmail(SingleEmailFailedRequest request) + { + var param0 = new SqlParameter("@p0", SqlDbType.NVarChar) { Value = request.Recipient }; + var param1 = new SqlParameter("@p1", SqlDbType.NVarChar) { Value = request.TemplateId }; + var param2 = new SqlParameter("@p2", SqlDbType.NVarChar) { Value = request.Personalisation }; + var param3 = new SqlParameter("@p3", SqlDbType.NVarChar) { Value = request.ErrorMessage }; + await this.dbContext.Database.ExecuteSqlRawAsync("dbo.SaveFailedSingleEmail @p0, @p1, @p2, @p3", param0, param1, param2, param3); + } + } +} diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing/Startup.cs b/MessageQueueing/LearningHub.Nhs.MessageQueueing/Startup.cs new file mode 100644 index 000000000..e3cfa65d1 --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing/Startup.cs @@ -0,0 +1,32 @@ +namespace LearningHub.Nhs.MessageQueueing +{ + using LearningHub.Nhs.MessageQueueing.EntityFramework; + using LearningHub.Nhs.MessageQueueing.Repositories; + using Microsoft.EntityFrameworkCore; + using Microsoft.Extensions.Configuration; + using Microsoft.Extensions.DependencyInjection; + + /// + /// Contains methods to configure the project to be called in an API startup class. + /// + public static class Startup + { + /// + /// Registers the implementations in the project with ASP.NET DI. + /// + /// The IServiceCollection. + /// The IConfiguration. + public static void AddQueueingRepositories(this IServiceCollection services, IConfiguration configuration) + { + var dbContextOptions = new DbContextOptionsBuilder() + .UseSqlServer(configuration.GetConnectionString("GovNotifyMessageDbConnection"), providerOptions => { providerOptions.EnableRetryOnFailure(3); }) + .Options; + + services.AddSingleton(dbContextOptions); + services.AddSingleton(); + + services.AddDbContext(); + services.AddScoped(); + } + } +} diff --git a/MessagingService/LearningHub.Nhs.MessagingService/Interfaces/IGovNotifyService.cs b/MessagingService/LearningHub.Nhs.MessagingService/Interfaces/IGovNotifyService.cs index 23d0d3738..588d766e7 100644 --- a/MessagingService/LearningHub.Nhs.MessagingService/Interfaces/IGovNotifyService.cs +++ b/MessagingService/LearningHub.Nhs.MessagingService/Interfaces/IGovNotifyService.cs @@ -2,6 +2,7 @@ { using System.Collections.Generic; using System.Threading.Tasks; + using LearningHub.Nhs.Models.GovNotifyMessaging; /// /// IMessageServices. @@ -15,7 +16,7 @@ public interface IGovNotifyService /// templateId. /// personalisation. /// The . - Task SendEmailAsync(string email, string templateId, Dictionary personalisation); + Task SendEmailAsync(string email, string templateId, Dictionary personalisation); /// /// Send SmsAsync. @@ -24,6 +25,6 @@ public interface IGovNotifyService /// templateId. /// personalisation. /// The . - Task SendSmsAsync(string phoneNumber, string templateId, Dictionary personalisation); + Task SendSmsAsync(string phoneNumber, string templateId, Dictionary personalisation); } } diff --git a/MessagingService/LearningHub.Nhs.MessagingService/LearningHub.Nhs.MessagingService.csproj b/MessagingService/LearningHub.Nhs.MessagingService/LearningHub.Nhs.MessagingService.csproj index d21593e42..bd12f3577 100644 --- a/MessagingService/LearningHub.Nhs.MessagingService/LearningHub.Nhs.MessagingService.csproj +++ b/MessagingService/LearningHub.Nhs.MessagingService/LearningHub.Nhs.MessagingService.csproj @@ -8,6 +8,7 @@ + diff --git a/MessagingService/LearningHub.Nhs.MessagingService/Model/MessagingServiceModel.cs b/MessagingService/LearningHub.Nhs.MessagingService/MessagingOptions/MessagingServiceOptions.cs similarity index 80% rename from MessagingService/LearningHub.Nhs.MessagingService/Model/MessagingServiceModel.cs rename to MessagingService/LearningHub.Nhs.MessagingService/MessagingOptions/MessagingServiceOptions.cs index 66a3f210e..b4b395f31 100644 --- a/MessagingService/LearningHub.Nhs.MessagingService/Model/MessagingServiceModel.cs +++ b/MessagingService/LearningHub.Nhs.MessagingService/MessagingOptions/MessagingServiceOptions.cs @@ -3,12 +3,12 @@ /// /// MessagingServiceModel. /// - public class MessagingServiceModel + public class MessagingServiceOptions { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - public MessagingServiceModel() + public MessagingServiceOptions() { // Current = this; } diff --git a/MessagingService/LearningHub.Nhs.MessagingService/Model/SendEmailRequest.cs b/MessagingService/LearningHub.Nhs.MessagingService/Model/SendEmailRequest.cs deleted file mode 100644 index da0044425..000000000 --- a/MessagingService/LearningHub.Nhs.MessagingService/Model/SendEmailRequest.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace LearningHub.Nhs.MessagingService.Model -{ - using System.Collections.Generic; - using System.ComponentModel.DataAnnotations; - - /// - /// Defines the . - /// - public class SendEmailRequest - { - /// - /// Gets or Sets the Email. - /// - [Required] - public string Email { get; set; } - - /// - /// Gets or Sets the TemplateId. - /// - [Required] - public string TemplateId { get; set; } - - /// - /// Gets or Sets the Personalisation. - /// - public Dictionary Personalisation { get; set; } - } -} diff --git a/MessagingService/LearningHub.Nhs.MessagingService/Model/SendSmsRequest.cs b/MessagingService/LearningHub.Nhs.MessagingService/Model/SendSmsRequest.cs deleted file mode 100644 index cb2481cfe..000000000 --- a/MessagingService/LearningHub.Nhs.MessagingService/Model/SendSmsRequest.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace LearningHub.Nhs.MessagingService.Model -{ - using System.Collections.Generic; - using System.ComponentModel.DataAnnotations; - - /// - /// Defines the . - /// - public class SendSmsRequest - { - /// - /// Gets or Sets the PhoneNumber. - /// - [Required] - public string PhoneNumber { get; set; } - - /// - /// Gets or Sets the TemplateId. - /// - [Required] - public string TemplateId { get; set; } - - /// - /// Gets or Sets the Personalisation. - /// - public Dictionary Personalisation { get; set; } - } -} diff --git a/MessagingService/LearningHub.Nhs.MessagingService/Services/GovNotifyService.cs b/MessagingService/LearningHub.Nhs.MessagingService/Services/GovNotifyService.cs index b81c8e7b2..9d06a21e6 100644 --- a/MessagingService/LearningHub.Nhs.MessagingService/Services/GovNotifyService.cs +++ b/MessagingService/LearningHub.Nhs.MessagingService/Services/GovNotifyService.cs @@ -6,8 +6,10 @@ using System.Threading.Tasks; using LearningHub.Nhs.MessagingService.Interfaces; using LearningHub.Nhs.MessagingService.Model; + using LearningHub.Nhs.Models.GovNotifyMessaging; using Microsoft.Extensions.Options; using Notify.Client; + using Notify.Exceptions; /// /// GovNotify Service class. @@ -18,10 +20,9 @@ public class GovNotifyService : IGovNotifyService /// /// Initializes a new instance of the class. - /// GovNotifyService. /// - /// The Messaging Service Model. - public GovNotifyService(IOptions options) + /// The Messaging Service Options. + public GovNotifyService(IOptions options) { this.client = new NotificationClient(options.Value.GovNotifyApiKey); } @@ -35,26 +36,52 @@ public GovNotifyService(IOptions options) /// A dictionary containing key-value pairs for personalising the email template. /// Keys should match the placeholders in the Gov.Notify template. /// - /// - /// A unique message ID representing the queued email. - /// - public async Task SendEmailAsync(string email, string templateId, Dictionary personalisation) + /// The . + public async Task SendEmailAsync(string email, string templateId, Dictionary personalisation) { - var normalisedPersonlisation = new Dictionary(); - foreach (var item in personalisation) + try { - if (item.Value is JsonElement element) + var normalisedPersonlisation = new Dictionary(); + if (personalisation != null) + { + foreach (var item in personalisation) + { + if (item.Value is JsonElement element) + { + normalisedPersonlisation[item.Key] = element.ToString(); + } + else + { + normalisedPersonlisation[item.Key] = item.Value; + } + } + } + + var response = await this.client.SendEmailAsync(email, templateId, normalisedPersonlisation); + return new GovNotifyResponse { - normalisedPersonlisation[item.Key] = element.ToString(); - } - else + IsSuccess = true, + NotificationId = response.id, + }; + } + catch (NotifyClientException ex) + { + return new GovNotifyResponse { - normalisedPersonlisation[item.Key] = item.Value; - } + IsSuccess = false, + ErrorMessage = ex.Message, + ////Retry = true, + }; + } + catch (Exception ex) + { + return new GovNotifyResponse + { + IsSuccess = false, + ErrorMessage = ex.Message, + ////Retry = true, + }; } - - var response = await this.client.SendEmailAsync(email, templateId, normalisedPersonlisation); - return response.id; } /// @@ -66,26 +93,49 @@ public async Task SendEmailAsync(string email, string templateId, Dictio /// A dictionary containing key-value pairs for personalising the SMS template. /// Keys should match the placeholders in the Gov.Notify template. /// - /// - /// A unique message ID representing the queued SMS. - /// - public async Task SendSmsAsync(string phoneNumber, string templateId, Dictionary personalisation) + /// The . + public async Task SendSmsAsync(string phoneNumber, string templateId, Dictionary personalisation) { - var normalisedPersonlisation = new Dictionary(); - foreach (var item in personalisation) + try { - if (item.Value is JsonElement element) + var normalisedPersonlisation = new Dictionary(); + foreach (var item in personalisation) { - normalisedPersonlisation[item.Key] = element.ToString(); + if (item.Value is JsonElement element) + { + normalisedPersonlisation[item.Key] = element.ToString(); + } + else + { + normalisedPersonlisation[item.Key] = item.Value; + } } - else + + var response = await this.client.SendSmsAsync(phoneNumber, templateId, normalisedPersonlisation); + return new GovNotifyResponse { - normalisedPersonlisation[item.Key] = item.Value; - } + IsSuccess = true, + NotificationId = response.id, + }; + } + catch (NotifyClientException ex) + { + return new GovNotifyResponse + { + IsSuccess = false, + ErrorMessage = ex.Message, + ////Retry = true, + }; + } + catch (Exception ex) + { + return new GovNotifyResponse + { + IsSuccess = false, + ErrorMessage = ex.Message, + ////Retry = true, + }; } - - var response = await this.client.SendSmsAsync(phoneNumber, templateId, normalisedPersonlisation); - return response.id; } } } diff --git a/MessagingService/LearningHub.Nhs.MessagingService/Startup.cs b/MessagingService/LearningHub.Nhs.MessagingService/Startup.cs index 522b98bda..30359eb08 100644 --- a/MessagingService/LearningHub.Nhs.MessagingService/Startup.cs +++ b/MessagingService/LearningHub.Nhs.MessagingService/Startup.cs @@ -18,7 +18,7 @@ public static class Startup /// The IConfiguration. public static void AddMessagingServices(this IServiceCollection services, IConfiguration configuration) { - services.Configure(configuration.GetSection("GovNotify")); + services.Configure(configuration.GetSection("GovNotify")); services.AddScoped(); } } diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Models/LearningHub.Nhs.OpenApi.Models.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Models/LearningHub.Nhs.OpenApi.Models.csproj index f34790d51..a4341e802 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Models/LearningHub.Nhs.OpenApi.Models.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Models/LearningHub.Nhs.OpenApi.Models.csproj @@ -16,7 +16,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/LearningHub.Nhs.OpenApi.Services.Interface.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/LearningHub.Nhs.OpenApi.Services.Interface.csproj index 20b3a1c06..d3907645f 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/LearningHub.Nhs.OpenApi.Services.Interface.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/LearningHub.Nhs.OpenApi.Services.Interface.csproj @@ -17,7 +17,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj index f84d5121c..b7850fdea 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj @@ -30,7 +30,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/GovNotifyMessagingController.cs b/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/GovNotifyMessagingController.cs index 05066a292..574b9dced 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/GovNotifyMessagingController.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/GovNotifyMessagingController.cs @@ -1,11 +1,16 @@ namespace LearningHub.NHS.OpenAPI.Controllers { using System; + using System.Collections.Generic; + using System.Linq; using System.Threading.Tasks; + using LearningHub.Nhs.MessageQueueing.Repositories; using LearningHub.Nhs.MessagingService.Interfaces; - using LearningHub.Nhs.MessagingService.Model; + using LearningHub.Nhs.Models.Entities.GovNotifyMessaging; + using LearningHub.Nhs.Models.GovNotifyMessaging; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; + using Newtonsoft.Json; /// /// GovNotify Messaging Controller. @@ -15,14 +20,17 @@ public class GovNotifyMessagingController : OpenApiControllerBase { private readonly IGovNotifyService messageService; + private readonly IMessageQueueRepository messageQueueRepository; /// /// Initializes a new instance of the class. /// - /// The catalogue service. - public GovNotifyMessagingController(IGovNotifyService messageService) + /// The message service. + /// The email Queue Repository. + public GovNotifyMessagingController(IGovNotifyService messageService, IMessageQueueRepository messageQueueRepository) { this.messageService = messageService; + this.messageQueueRepository = messageQueueRepository; } /// @@ -30,18 +38,35 @@ public GovNotifyMessagingController(IGovNotifyService messageService) /// /// personalisation. /// The . - [Route("sendemail")] + [Route("SendEmail")] [HttpPost] - public async Task SendEmailAsync([FromBody] SendEmailRequest request) + public async Task SendEmailAsync([FromBody] EmailRequest request) { try { - if (string.IsNullOrWhiteSpace(request.Email) || string.IsNullOrWhiteSpace(request.TemplateId)) + if (string.IsNullOrWhiteSpace(request.Recipient) || string.IsNullOrWhiteSpace(request.TemplateId)) { return this.BadRequest("Email and template ID are required"); } - var response = await this.messageService.SendEmailAsync(request.Email, request.TemplateId, request.Personalisation); + var response = await this.messageService.SendEmailAsync(request.Recipient, request.TemplateId, request.Personalisation); + + Dictionary test = new Dictionary(); + if (response != null) + { + if (!response.IsSuccess && (request.Id == null || request.Id <= 0)) + { + var failedRequest = new SingleEmailFailedRequest + { + Recipient = request.Recipient, + TemplateId = request.TemplateId, + Personalisation = request.Personalisation != null ? JsonConvert.SerializeObject(request.Personalisation.ToDictionary(kvp => kvp.Key, kvp => kvp.Value?.ToString())) : null, + ErrorMessage = response.ErrorMessage, + }; + await this.messageQueueRepository.SaveFailedSingleEmail(failedRequest); + } + } + return this.Ok(response); } catch (Exception ex) @@ -55,9 +80,9 @@ public async Task SendEmailAsync([FromBody] SendEmailRequest requ /// /// SendSmsRequest. /// The . - [Route("sendsms")] + [Route("SendSms")] [HttpPost] - public async Task SendSmsAsync([FromBody] SendSmsRequest request) + public async Task SendSmsAsync([FromBody] SmsRequest request) { try { @@ -74,5 +99,69 @@ public async Task SendSmsAsync([FromBody] SendSmsRequest request) return this.Ok(ex.Message); } } + + /// + /// To queue the MessageRequests. + /// + /// The QueueRequestList. + /// The . + [Route("QueueRequests")] + [HttpPost] + public async Task QueueRequests([FromBody] QueueMessageList request) + { + if (request?.Messages == null || !request.Messages.Any()) + { + return this.BadRequest("At least one email must be provided in the request."); + } + + var requests = request.Messages.Select(q => new QueueRequests + { + Recipient = q.Recipient, + TemplateId = q.TemplateId, + Personalisation = q.Personalisation != null ? JsonConvert.SerializeObject(q.Personalisation) : null, + DeliverAfter = q.DeliverAfter ?? null, + }); + + await this.messageQueueRepository.QueueMessagesAsync(requests); + + return this.Ok(new { Message = $"{requests.Count()} message requests queued successfully." }); + } + + /// + /// To fetch the Pending or failed Message Requests. + /// + /// The . + [Route("PendingMessageRequests")] + [HttpGet] + public async Task> PendingMessageRequests() + { + return await this.messageQueueRepository.GetPendingEmailsAsync(); + } + + /// + /// Update message request as Success. + /// + /// The response. + /// The . + [Route("MessageSuccessUpdate")] + [HttpPost] + public async Task MessageSuccessUpdate([FromBody] GovNotifyResponse response) + { + await this.messageQueueRepository.MessageDeliverySuccess(response); + return this.Ok(); + } + + /// + /// Update message request as Failed. + /// + /// The response. + /// The . + [Route("MessageFailedUpdate")] + [HttpPost] + public async Task MessageFailedUpdate([FromBody] GovNotifyResponse response) + { + await this.messageQueueRepository.MessageDeliveryFailed(response); + return this.Ok(); + } } } diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj b/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj index 56f52c05e..5969f63c9 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj @@ -31,6 +31,7 @@ + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/Startup.cs b/OpenAPI/LearningHub.Nhs.OpenApi/Startup.cs index f3dc3f51b..ea03ad70f 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi/Startup.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi/Startup.cs @@ -31,6 +31,8 @@ namespace LearningHub.NHS.OpenAPI using System; using LearningHub.Nhs.Models.Extensions; using LearningHub.Nhs.MessagingService; + using LearningHub.Nhs.MessageQueueing; + using Microsoft.AspNetCore.Authentication.Cookies; /// /// The Startup class. @@ -60,6 +62,7 @@ public void ConfigureServices(IServiceCollection services) services.AddConfig(this.Configuration); services.AddApiKeyAuth(); + services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(); services.AddAuthentication() .AddJwtBearer(options => @@ -86,6 +89,7 @@ public void ConfigureServices(IServiceCollection services) services.AddControllers(options => options.Filters.Add(new HttpResponseExceptionFilter())); services.AddControllers(opt => { opt.Filters.Add(new AuthorizeFilter()); }); services.AddMessagingServices(this.Configuration); + services.AddQueueingRepositories(this.Configuration); services.AddSwaggerGen( c => { diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/SwaggerDefinitions/v1.3.0.json b/OpenAPI/LearningHub.Nhs.OpenApi/SwaggerDefinitions/v1.3.0.json index 9633b6117..00bb8cf37 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi/SwaggerDefinitions/v1.3.0.json +++ b/OpenAPI/LearningHub.Nhs.OpenApi/SwaggerDefinitions/v1.3.0.json @@ -6034,29 +6034,28 @@ } } }, - "/GovNotifyMessage/sendsms": { + "/GovNotifyMessage/SendSms": { "post": { "tags": [ "SendSms" ], "summary": "Send an SMS.", - "required": [ "mobileNumber", "templateId" ], "requestBody": { "description": "The Sends an SMS using the UK Gov.Notify service.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SendSmsRequest" + "$ref": "#/components/schemas/LearningHub.Nhs.Models.GovNotifyMessaging.SmsRequest" } }, "text/json": { "schema": { - "$ref": "#/components/schemas/SendSmsRequest" + "$ref": "#/components/schemas/LearningHub.Nhs.Models.GovNotifyMessaging.SmsRequest" } }, "application/*+json": { "schema": { - "$ref": "#/components/schemas/SendSmsRequest" + "$ref": "#/components/schemas/LearningHub.Nhs.Models.GovNotifyMessaging.SmsRequest" } } } @@ -6074,7 +6073,7 @@ } } }, - "/GovNotifyMessage/sendemail": { + "/GovNotifyMessage/SendEmail": { "post": { "tags": [ "SendEmail" @@ -6085,17 +6084,17 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SendEmailRequest" + "$ref": "#/components/schemas/LearningHub.Nhs.Models.GovNotifyMessaging.EmailRequest" } }, "text/json": { "schema": { - "$ref": "#/components/schemas/SendEmailRequest" + "$ref": "#/components/schemas/LearningHub.Nhs.Models.GovNotifyMessaging.EmailRequest" } }, "application/*+json": { "schema": { - "$ref": "#/components/schemas/SendEmailRequest" + "$ref": "#/components/schemas/LearningHub.Nhs.Models.GovNotifyMessaging.EmailRequest" } } } @@ -6112,6 +6111,45 @@ } } } + }, + "/GovNotifyMessage/QueueRequests": { + "post": { + "tags": [ + "QueueRequests" + ], + "summary": "Queue one or more email/sms request for later processing.", + "requestBody": { + "description": "A list of sms/email requests to be queued for sending.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LearningHub.Nhs.Models.GovNotifyMessaging.QueueRequestsList" + } + }, + "text/json": { + "schema": { + "$ref": "#/components/schemas/LearningHub.Nhs.Models.GovNotifyMessaging.QueueRequestsList" + } + }, + "application/*+json": { + "schema": { + "$ref": "#/components/schemas/LearningHub.Nhs.Models.GovNotifyMessaging.QueueRequestsList" + } + } + } + }, + "responses": { + "200": { + "description": "Requests are queued successfully." + }, + "400": { + "description": "Bad request, invalid input." + }, + "500": { + "description": "Internal server error." + } + } + } } }, "components": { @@ -14218,50 +14256,85 @@ }, "additionalProperties": false }, - "SendSmsRequest": { + "LearningHub.Nhs.Models.GovNotifyMessaging.SmsRequest": { "type": "object", - "required": [ "mobileNumber", "templateId" ], + "required": [ "PhoneNumber", "TemplateId" ], "properties": { - "mobileNumber": { + "PhoneNumber": { "type": "string", "nullable": false, "description": "The recipient's mobile number." }, - "templateId": { + "TemplateId": { "type": "string", "nullable": false, "description": "The ID of the template to be used for the email." }, - "personalisation": { + "Personalisation": { "type": "object", - "additionalProperties:": { + "additionalProperties": { "type": "string" }, "description": "Key-value pairs for personalising the sms template." } } }, - "SendEmailRequest": { + "LearningHub.Nhs.Models.GovNotifyMessaging.EmailRequest": { "type": "object", "properties": { - "emailAddress": { + "Recipient": { "type": "string", "nullable": false, "description": "The recipient's email address." }, - "templateId": { + "TemplateId": { "type": "string", "nullable": false, "description": "The ID of the template to be used for the email." }, - "personalisation": { + "Personalisation": { "type": "object", - "additionalProperties:": { + "additionalProperties": { "type": "string" }, "description": "Key-value pairs for personalising the email template." } } + }, + "LearningHub.Nhs.Models.GovNotifyMessaging.QueueRequestsList": { + "type": "object", + "properties": { + "Messages": { + "type": "array", + "items": { + "$ref": "#/components/schemas/LearningHub.Nhs.Models.GovNotifyMessaging.QueueRequests" + } + } + } + }, + "LearningHub.Nhs.Models.GovNotifyMessaging.QueueRequests": { + "type": "object", + "properties": { + "Recipient": { + "type": "string", + "nullable": false + }, + "TemplateId": { + "type": "string", + "nullable": false + }, + "DeliverAfter": { + "type": "string", + "format": "date-time" + }, + "Personalisation": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Key-value pairs for personalising the template." + } + } } }, "securitySchemes": { diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/appsettings.json b/OpenAPI/LearningHub.Nhs.OpenApi/appsettings.json index 56c507cff..f9c27f84e 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi/appsettings.json +++ b/OpenAPI/LearningHub.Nhs.OpenApi/appsettings.json @@ -11,6 +11,7 @@ "ElfhHubDbConnection": "", "LearningHubDbConnection": "", "LearningHubRedis": "", + "GovNotifyMessageDbConnection": "", "NLogDb": "" }, "Auth": { @@ -38,6 +39,12 @@ "Keys": [ "" ] + }, + { + "Name": "MessageQueueProcessor", + "Keys": [ + "" + ] } ] }, diff --git a/ReportAPI/LearningHub.Nhs.ReportApi.Services.Interface/LearningHub.Nhs.ReportApi.Services.Interface.csproj b/ReportAPI/LearningHub.Nhs.ReportApi.Services.Interface/LearningHub.Nhs.ReportApi.Services.Interface.csproj index 0a697a51f..655caa351 100644 --- a/ReportAPI/LearningHub.Nhs.ReportApi.Services.Interface/LearningHub.Nhs.ReportApi.Services.Interface.csproj +++ b/ReportAPI/LearningHub.Nhs.ReportApi.Services.Interface/LearningHub.Nhs.ReportApi.Services.Interface.csproj @@ -16,7 +16,7 @@ - + diff --git a/ReportAPI/LearningHub.Nhs.ReportApi.Services.UnitTests/LearningHub.Nhs.ReportApi.Services.UnitTests.csproj b/ReportAPI/LearningHub.Nhs.ReportApi.Services.UnitTests/LearningHub.Nhs.ReportApi.Services.UnitTests.csproj index 50e3d7536..537f585bd 100644 --- a/ReportAPI/LearningHub.Nhs.ReportApi.Services.UnitTests/LearningHub.Nhs.ReportApi.Services.UnitTests.csproj +++ b/ReportAPI/LearningHub.Nhs.ReportApi.Services.UnitTests/LearningHub.Nhs.ReportApi.Services.UnitTests.csproj @@ -18,7 +18,7 @@ - + diff --git a/ReportAPI/LearningHub.Nhs.ReportApi.Services/LearningHub.Nhs.ReportApi.Services.csproj b/ReportAPI/LearningHub.Nhs.ReportApi.Services/LearningHub.Nhs.ReportApi.Services.csproj index 55c8a1be4..42d7766fc 100644 --- a/ReportAPI/LearningHub.Nhs.ReportApi.Services/LearningHub.Nhs.ReportApi.Services.csproj +++ b/ReportAPI/LearningHub.Nhs.ReportApi.Services/LearningHub.Nhs.ReportApi.Services.csproj @@ -19,7 +19,7 @@ - + diff --git a/ReportAPI/LearningHub.Nhs.ReportApi.Shared/LearningHub.Nhs.ReportApi.Shared.csproj b/ReportAPI/LearningHub.Nhs.ReportApi.Shared/LearningHub.Nhs.ReportApi.Shared.csproj index 2f5518784..5b6a9d92e 100644 --- a/ReportAPI/LearningHub.Nhs.ReportApi.Shared/LearningHub.Nhs.ReportApi.Shared.csproj +++ b/ReportAPI/LearningHub.Nhs.ReportApi.Shared/LearningHub.Nhs.ReportApi.Shared.csproj @@ -17,7 +17,7 @@ - + diff --git a/ReportAPI/LearningHub.Nhs.ReportApi/LearningHub.Nhs.ReportApi.csproj b/ReportAPI/LearningHub.Nhs.ReportApi/LearningHub.Nhs.ReportApi.csproj index 583caa9f2..b215db06c 100644 --- a/ReportAPI/LearningHub.Nhs.ReportApi/LearningHub.Nhs.ReportApi.csproj +++ b/ReportAPI/LearningHub.Nhs.ReportApi/LearningHub.Nhs.ReportApi.csproj @@ -20,7 +20,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj b/WebAPI/LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj index bb0c6c6cc..37286151e 100644 --- a/WebAPI/LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj +++ b/WebAPI/LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj @@ -29,7 +29,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Api.Shared/LearningHub.Nhs.Api.Shared.csproj b/WebAPI/LearningHub.Nhs.Api.Shared/LearningHub.Nhs.Api.Shared.csproj index 74d2ccc77..8173a68b2 100644 --- a/WebAPI/LearningHub.Nhs.Api.Shared/LearningHub.Nhs.Api.Shared.csproj +++ b/WebAPI/LearningHub.Nhs.Api.Shared/LearningHub.Nhs.Api.Shared.csproj @@ -9,7 +9,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/WebAPI/LearningHub.Nhs.Api.UnitTests/LearningHub.Nhs.Api.UnitTests.csproj b/WebAPI/LearningHub.Nhs.Api.UnitTests/LearningHub.Nhs.Api.UnitTests.csproj index 9663e4ee7..ca8916c4e 100644 --- a/WebAPI/LearningHub.Nhs.Api.UnitTests/LearningHub.Nhs.Api.UnitTests.csproj +++ b/WebAPI/LearningHub.Nhs.Api.UnitTests/LearningHub.Nhs.Api.UnitTests.csproj @@ -11,7 +11,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Repository.Interface/LearningHub.Nhs.Repository.Interface.csproj b/WebAPI/LearningHub.Nhs.Repository.Interface/LearningHub.Nhs.Repository.Interface.csproj index d41ba9e68..1c2dfe61b 100644 --- a/WebAPI/LearningHub.Nhs.Repository.Interface/LearningHub.Nhs.Repository.Interface.csproj +++ b/WebAPI/LearningHub.Nhs.Repository.Interface/LearningHub.Nhs.Repository.Interface.csproj @@ -10,7 +10,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Repository/LearningHub.Nhs.Repository.csproj b/WebAPI/LearningHub.Nhs.Repository/LearningHub.Nhs.Repository.csproj index 904bda4c8..a84412769 100644 --- a/WebAPI/LearningHub.Nhs.Repository/LearningHub.Nhs.Repository.csproj +++ b/WebAPI/LearningHub.Nhs.Repository/LearningHub.Nhs.Repository.csproj @@ -9,7 +9,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Services.Interface/LearningHub.Nhs.Services.Interface.csproj b/WebAPI/LearningHub.Nhs.Services.Interface/LearningHub.Nhs.Services.Interface.csproj index b259b3a7e..c76a6ee5c 100644 --- a/WebAPI/LearningHub.Nhs.Services.Interface/LearningHub.Nhs.Services.Interface.csproj +++ b/WebAPI/LearningHub.Nhs.Services.Interface/LearningHub.Nhs.Services.Interface.csproj @@ -16,7 +16,7 @@ - + all diff --git a/WebAPI/LearningHub.Nhs.Services.UnitTests/LearningHub.Nhs.Services.UnitTests.csproj b/WebAPI/LearningHub.Nhs.Services.UnitTests/LearningHub.Nhs.Services.UnitTests.csproj index f78df0084..06af56b2a 100644 --- a/WebAPI/LearningHub.Nhs.Services.UnitTests/LearningHub.Nhs.Services.UnitTests.csproj +++ b/WebAPI/LearningHub.Nhs.Services.UnitTests/LearningHub.Nhs.Services.UnitTests.csproj @@ -13,7 +13,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Services/LearningHub.Nhs.Services.csproj b/WebAPI/LearningHub.Nhs.Services/LearningHub.Nhs.Services.csproj index e99e5300a..903884270 100644 --- a/WebAPI/LearningHub.Nhs.Services/LearningHub.Nhs.Services.csproj +++ b/WebAPI/LearningHub.Nhs.Services/LearningHub.Nhs.Services.csproj @@ -13,7 +13,7 @@ - + diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.ConsoleApp/LearningHub.Nhs.Migration.ConsoleApp.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.ConsoleApp/LearningHub.Nhs.Migration.ConsoleApp.csproj index 697d1db2f..3119248d5 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.ConsoleApp/LearningHub.Nhs.Migration.ConsoleApp.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.ConsoleApp/LearningHub.Nhs.Migration.ConsoleApp.csproj @@ -25,7 +25,7 @@ - + all diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Interface/LearningHub.Nhs.Migration.Interface.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Interface/LearningHub.Nhs.Migration.Interface.csproj index 89ca1344e..bc30ad48a 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Interface/LearningHub.Nhs.Migration.Interface.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Interface/LearningHub.Nhs.Migration.Interface.csproj @@ -9,7 +9,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Models/LearningHub.Nhs.Migration.Models.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Models/LearningHub.Nhs.Migration.Models.csproj index 4ab608bac..5ab9d00b1 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Models/LearningHub.Nhs.Migration.Models.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Models/LearningHub.Nhs.Migration.Models.csproj @@ -10,7 +10,7 @@ - + all diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Staging.Repository/LearningHub.Nhs.Migration.Staging.Repository.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Staging.Repository/LearningHub.Nhs.Migration.Staging.Repository.csproj index 7dd7febb7..539446335 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Staging.Repository/LearningHub.Nhs.Migration.Staging.Repository.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Staging.Repository/LearningHub.Nhs.Migration.Staging.Repository.csproj @@ -9,7 +9,7 @@ - + diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.UnitTests/LearningHub.Nhs.Migration.UnitTests.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.UnitTests/LearningHub.Nhs.Migration.UnitTests.csproj index 5b83ec893..693ef008d 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.UnitTests/LearningHub.Nhs.Migration.UnitTests.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.UnitTests/LearningHub.Nhs.Migration.UnitTests.csproj @@ -10,7 +10,7 @@ - + diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration/LearningHub.Nhs.Migration.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration/LearningHub.Nhs.Migration.csproj index bf0235325..a184bb27f 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration/LearningHub.Nhs.Migration.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration/LearningHub.Nhs.Migration.csproj @@ -12,7 +12,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive From 85e49e4cac4cb0ff61d12c4d8212043e7a6b6633 Mon Sep 17 00:00:00 2001 From: Arunima George Date: Mon, 9 Jun 2025 10:43:25 +0100 Subject: [PATCH 04/16] TD-5477: Added history details in SPs. --- .../Stored Procedures/CreateQueueRequests.sql | 12 +++++++++++- .../Stored Procedures/GetQueueRequests.sql | 12 +++++++++++- .../Stored Procedures/MessageDeliveryFailed.sql | 12 +++++++++++- .../Stored Procedures/MessageDeliverySuccess.sql | 12 +++++++++++- .../Stored Procedures/SaveFailedSingleEmail.sql | 12 +++++++++++- 5 files changed, 55 insertions(+), 5 deletions(-) diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/CreateQueueRequests.sql b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/CreateQueueRequests.sql index b9cd5d3d1..a7d8bb494 100644 --- a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/CreateQueueRequests.sql +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/CreateQueueRequests.sql @@ -1,4 +1,14 @@ -Create PROCEDURE [dbo].[CreateQueueRequests] +------------------------------------------------------------------------------- +-- Author Arunima George +-- Created 27-05-2025 +-- Purpose Create email requests. +-- +-- Modification History +-- +-- 27-05-2025 Arunima George Initial Revision +------------------------------------------------------------------------------- + +Create PROCEDURE [dbo].[CreateQueueRequests] @QueueRequests dbo.QueueRequestTableType READONLY AS BEGIN diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/GetQueueRequests.sql b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/GetQueueRequests.sql index a23cd61a6..7f2ac520c 100644 --- a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/GetQueueRequests.sql +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/GetQueueRequests.sql @@ -1,4 +1,14 @@ -CREATE PROCEDURE [dbo].[GetQueueRequests] +------------------------------------------------------------------------------- +-- Author Arunima George +-- Created 27-05-2025 +-- Purpose Fetch pending/failed email requests from QueueRequests table. +-- +-- Modification History +-- +-- 27-05-2025 Arunima George Initial Revision +------------------------------------------------------------------------------- + +CREATE PROCEDURE [dbo].[GetQueueRequests] AS BEGIN diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/MessageDeliveryFailed.sql b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/MessageDeliveryFailed.sql index 8c6b6b606..4d00ebac4 100644 --- a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/MessageDeliveryFailed.sql +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/MessageDeliveryFailed.sql @@ -1,4 +1,14 @@ -CREATE PROCEDURE [dbo].[MessageDeliveryFailed] +------------------------------------------------------------------------------- +-- Author Arunima George +-- Created 27-05-2025 +-- Purpose Update message request status as failed. +-- +-- Modification History +-- +-- 27-05-2025 Arunima George Initial Revision +------------------------------------------------------------------------------- + +CREATE PROCEDURE [dbo].[MessageDeliveryFailed] @Id int, @ErrorMessage nvarchar(max) AS diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/MessageDeliverySuccess.sql b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/MessageDeliverySuccess.sql index 73c18ebdd..b971d912f 100644 --- a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/MessageDeliverySuccess.sql +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/MessageDeliverySuccess.sql @@ -1,4 +1,14 @@ -CREATE PROCEDURE [dbo].[MessageDeliverySuccess] +------------------------------------------------------------------------------- +-- Author Arunima George +-- Created 27-05-2025 +-- Purpose Update message request status as success. +-- +-- Modification History +-- +-- 27-05-2025 Arunima George Initial Revision +------------------------------------------------------------------------------- + +CREATE PROCEDURE [dbo].[MessageDeliverySuccess] @Id int, @NotificationId nvarchar(100) diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/SaveFailedSingleEmail.sql b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/SaveFailedSingleEmail.sql index e9b9a849e..32a4c6395 100644 --- a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/SaveFailedSingleEmail.sql +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/SaveFailedSingleEmail.sql @@ -1,4 +1,14 @@ -CREATE PROCEDURE [dbo].[SaveFailedSingleEmail] +------------------------------------------------------------------------------- +-- Author Arunima George +-- Created 27-05-2025 +-- Purpose Save one-off(like otp emails) failed email request. +-- +-- Modification History +-- +-- 27-05-2025 Arunima George Initial Revision +------------------------------------------------------------------------------- + +CREATE PROCEDURE [dbo].[SaveFailedSingleEmail] @Recipient nvarchar(255), @TemplateId nvarchar(50), @Personalisation nvarchar(max), From 8044b464fc9287029fbc6d5ca0caebab6bf3723f Mon Sep 17 00:00:00 2001 From: swapnamol-abraham Date: Tue, 8 Jul 2025 09:02:41 +0100 Subject: [PATCH 05/16] TD-5736: Replace existing Web UI service SMTP notifications with Gov Notify messaging service equivalents --- ...rningHub.Nhs.WebUI.AutomatedUiTests.csproj | 1 + .../Controllers/Api/CatalogueController.cs | 2 +- .../Controllers/CatalogueController.cs | 10 +- .../Interfaces/ICatalogueService.cs | 3 +- .../Services/CatalogueService.cs | 5 +- .../Services/GovNotifyService.cs | 18 +- ....Nhs.OpenApi.Repositories.Interface.csproj | 1 + .../ICatalogueAccessRequestRepository.cs | 16 ++ .../EntityFramework/LearningHubDbContext.cs | 6 + ...earningHub.Nhs.OpenApi.Repositories.csproj | 1 + .../CatalogueAccessRequestRepository.cs | 33 ++++ .../Services/ICatalogueService.cs | 3 +- .../Messaging/IEmailTemplateService.cs | 8 + .../Services/Messaging/IGovMessageService.cs | 31 +++ .../LearningHub.Nhs.OpenApi.Services.csproj | 2 + .../Services/CatalogueService.cs | 186 +++++++++++++++--- .../Messaging/EmailTemplateService.cs | 11 ++ .../Services/Messaging/GovMessageService.cs | 106 ++++++++++ .../Startup.cs | 1 + .../LearningHub.Nhs.OpenApi.Tests.csproj | 1 + .../Services/CatalogueServiceTests.cs | 6 +- .../Controllers/CatalogueController.cs | 7 +- .../GovNotifyMessagingController.cs | 61 +++--- .../LearningHub.NHS.OpenAPI.csproj | 1 + OpenAPI/LearningHub.Nhs.OpenApi/Startup.cs | 1 + .../LearningHub.Nhs.Database.sqlproj | 3 + .../Scripts/UpdateEmailTemplateData.sql | 7 + .../Scripts/EmailTemplateTableChanges.sql | 2 + .../CatalogueAccessRequestCreate.sql | 127 ++++++------ .../Hierarchy/GetCatalogueAdminDetails.sql | 75 +++++++ 30 files changed, 586 insertions(+), 149 deletions(-) create mode 100644 OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/Messaging/IGovMessageService.cs create mode 100644 OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/Messaging/GovMessageService.cs create mode 100644 WebAPI/LearningHub.Nhs.Database/Scripts/Post-Deploy/Scripts/UpdateEmailTemplateData.sql create mode 100644 WebAPI/LearningHub.Nhs.Database/Scripts/Pre-Deploy/Scripts/EmailTemplateTableChanges.sql create mode 100644 WebAPI/LearningHub.Nhs.Database/Stored Procedures/Hierarchy/GetCatalogueAdminDetails.sql diff --git a/LearningHub.Nhs.WebUI.AutomatedUiTests/LearningHub.Nhs.WebUI.AutomatedUiTests.csproj b/LearningHub.Nhs.WebUI.AutomatedUiTests/LearningHub.Nhs.WebUI.AutomatedUiTests.csproj index d6bf3cd0d..eba5ce4b4 100644 --- a/LearningHub.Nhs.WebUI.AutomatedUiTests/LearningHub.Nhs.WebUI.AutomatedUiTests.csproj +++ b/LearningHub.Nhs.WebUI.AutomatedUiTests/LearningHub.Nhs.WebUI.AutomatedUiTests.csproj @@ -12,6 +12,7 @@ + diff --git a/LearningHub.Nhs.WebUI/Controllers/Api/CatalogueController.cs b/LearningHub.Nhs.WebUI/Controllers/Api/CatalogueController.cs index 0bec9e8d3..aca03ca60 100644 --- a/LearningHub.Nhs.WebUI/Controllers/Api/CatalogueController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/Api/CatalogueController.cs @@ -129,7 +129,7 @@ public async Task GetLatestCatalogueAccessRequestAsync(int catalo [HttpPost("catalogue/RequestAccess/{reference}")] public async Task RequestAccess(string reference, CatalogueAccessRequestViewModel vm) { - return this.Ok(await this.catalogueService.RequestAccessAsync(reference, vm, "access")); + return this.Ok(await this.catalogueService.RequestAccessAsync(reference, null, vm, "access")); } /// diff --git a/LearningHub.Nhs.WebUI/Controllers/CatalogueController.cs b/LearningHub.Nhs.WebUI/Controllers/CatalogueController.cs index 12d9973ac..ea843d125 100644 --- a/LearningHub.Nhs.WebUI/Controllers/CatalogueController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/CatalogueController.cs @@ -439,7 +439,8 @@ public async Task RequestAccess(CatalogueRequestAccessViewModel v { if (this.ModelState.IsValid) { - var validationResult = await this.catalogueService.RequestAccessAsync(viewModel.CatalogueUrl, new CatalogueAccessRequestViewModel() { Message = viewModel.AccessRequestMessage, RoleId = (int)RoleEnum.Reader }, "access"); + var userFullName = viewModel.CurrentUser.FirstName + " " + viewModel.CurrentUser.LastName; + var validationResult = await this.catalogueService.RequestAccessAsync(viewModel.CatalogueUrl, viewModel.CatalogueName, new CatalogueAccessRequestViewModel() { Message = viewModel.AccessRequestMessage, RoleId = (int)RoleEnum.Reader, EmailAddress = viewModel.CurrentUser.EmailAddress, UserFullName = userFullName }, "access"); if (validationResult.IsValid) { @@ -521,7 +522,8 @@ public async Task RequestPermission(CatalogueRequestAccessViewMod { if (this.ModelState.IsValid) { - var validationResult = await this.catalogueService.RequestAccessAsync(viewModel.CatalogueUrl, new CatalogueAccessRequestViewModel() { Message = viewModel.AccessRequestMessage, RoleId = (int)RoleEnum.Previewer }, "permission"); + var userFullName = viewModel.CurrentUser.FirstName + " " + viewModel.CurrentUser.LastName; + var validationResult = await this.catalogueService.RequestAccessAsync(viewModel.CatalogueUrl, viewModel.CatalogueName, new CatalogueAccessRequestViewModel() { Message = viewModel.AccessRequestMessage, RoleId = (int)RoleEnum.Previewer, EmailAddress = viewModel.CurrentUser.EmailAddress, UserFullName = userFullName }, "permission"); if (validationResult.IsValid) { @@ -555,7 +557,9 @@ public async Task RequestPreviewAccess(CatalogueRequestAccessView { if (this.ModelState.IsValid) { - var validationResult = await this.catalogueService.RequestAccessAsync(viewModel.CatalogueUrl, new CatalogueAccessRequestViewModel() { Message = viewModel.AccessRequestMessage, RoleId = (int)RoleEnum.Previewer }, "access"); + var userFullName = viewModel.CurrentUser.FirstName + " " + viewModel.CurrentUser.LastName; + + var validationResult = await this.catalogueService.RequestAccessAsync(viewModel.CatalogueUrl, viewModel.CatalogueName, new CatalogueAccessRequestViewModel() { Message = viewModel.AccessRequestMessage, RoleId = (int)RoleEnum.Previewer, EmailAddress = viewModel.CurrentUser.EmailAddress, UserFullName = userFullName }, "access"); if (validationResult.IsValid) { diff --git a/LearningHub.Nhs.WebUI/Interfaces/ICatalogueService.cs b/LearningHub.Nhs.WebUI/Interfaces/ICatalogueService.cs index e7770fd86..92ddc87e4 100644 --- a/LearningHub.Nhs.WebUI/Interfaces/ICatalogueService.cs +++ b/LearningHub.Nhs.WebUI/Interfaces/ICatalogueService.cs @@ -69,10 +69,11 @@ public interface ICatalogueService /// The RequestAccessAsync. /// /// The catalogue reference. + /// The catalogue name. /// The view model. /// The accessType. /// The task. - Task RequestAccessAsync(string reference, CatalogueAccessRequestViewModel vm, string accessType); + Task RequestAccessAsync(string reference, string catalogueName, CatalogueAccessRequestViewModel vm, string accessType); /// /// The InviteUserAsync. diff --git a/LearningHub.Nhs.WebUI/Services/CatalogueService.cs b/LearningHub.Nhs.WebUI/Services/CatalogueService.cs index 3833a4e28..dd2766f2e 100644 --- a/LearningHub.Nhs.WebUI/Services/CatalogueService.cs +++ b/LearningHub.Nhs.WebUI/Services/CatalogueService.cs @@ -269,12 +269,13 @@ public async Task GetLatestCatalogueAccessReque /// The RequestAccessAsync. /// /// The catalogue reference. + /// The catalogue catalogueName. /// The view model. /// The accessType. /// The task. - public async Task RequestAccessAsync(string reference, CatalogueAccessRequestViewModel vm, string accessType) + public async Task RequestAccessAsync(string reference, string catalogueName, CatalogueAccessRequestViewModel vm, string accessType) { - var request = $"Catalogue/RequestAccess/{reference}/{accessType}"; + var request = $"Catalogue/RequestAccess/{reference}/{catalogueName}/{accessType}"; var client = await this.OpenApiHttpClient.GetClientAsync(); var content = new StringContent(JsonConvert.SerializeObject(vm), Encoding.UTF8, "application/json"); diff --git a/MessagingService/LearningHub.Nhs.MessagingService/Services/GovNotifyService.cs b/MessagingService/LearningHub.Nhs.MessagingService/Services/GovNotifyService.cs index 9d06a21e6..e7eeef4f7 100644 --- a/MessagingService/LearningHub.Nhs.MessagingService/Services/GovNotifyService.cs +++ b/MessagingService/LearningHub.Nhs.MessagingService/Services/GovNotifyService.cs @@ -43,19 +43,19 @@ public async Task SendEmailAsync(string email, string templat { var normalisedPersonlisation = new Dictionary(); if (personalisation != null) + { + foreach (var item in personalisation) { - foreach (var item in personalisation) + if (item.Value is JsonElement element) + { + normalisedPersonlisation[item.Key] = element.ToString(); + } + else { - if (item.Value is JsonElement element) - { - normalisedPersonlisation[item.Key] = element.ToString(); - } - else - { - normalisedPersonlisation[item.Key] = item.Value; - } + normalisedPersonlisation[item.Key] = item.Value; } } + } var response = await this.client.SendEmailAsync(email, templateId, normalisedPersonlisation); return new GovNotifyResponse diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/LearningHub.Nhs.OpenApi.Repositories.Interface.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/LearningHub.Nhs.OpenApi.Repositories.Interface.csproj index 3444f18a2..61795062e 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/LearningHub.Nhs.OpenApi.Repositories.Interface.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/LearningHub.Nhs.OpenApi.Repositories.Interface.csproj @@ -17,6 +17,7 @@ + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Hierarchy/ICatalogueAccessRequestRepository.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Hierarchy/ICatalogueAccessRequestRepository.cs index 05fa86695..f295950fe 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Hierarchy/ICatalogueAccessRequestRepository.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/Repositories/Hierarchy/ICatalogueAccessRequestRepository.cs @@ -1,8 +1,10 @@ namespace LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories.Hierarchy { + using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using LearningHub.Nhs.Models.Entities.Hierarchy; + using LearningHub.Nhs.Models.Hierarchy; /// /// The ICatalogueAccessRequestRepository interface. @@ -42,5 +44,19 @@ Task CreateCatalogueAccessRequestAsync( int roleId, string catalogueManageAccessUrl, string accessType); + + /// + /// The GetCatalogueAdminDetailsAsync. + /// + /// The currentUserId. + /// The reference. + /// The roleId. + /// The accessType. + /// The task. + Task> GetCatalogueAdminDetailsAsync( + int currentUserId, + string reference, + int roleId, + string accessType); } } diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/EntityFramework/LearningHubDbContext.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/EntityFramework/LearningHubDbContext.cs index d055990ce..d859a4903 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/EntityFramework/LearningHubDbContext.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/EntityFramework/LearningHubDbContext.cs @@ -19,6 +19,7 @@ namespace LearningHub.Nhs.OpenApi.Repositories.EntityFramework using LearningHub.Nhs.Models.Resource.ResourceDisplay; using LearningHub.Nhs.Models.User; using Microsoft.EntityFrameworkCore; + using CatalogueAdminViewModel = LearningHub.Nhs.Models.Hierarchy.CatalogueAdminViewModel; using Event = LearningHub.Nhs.Models.Entities.Analytics.Event; /// @@ -393,6 +394,11 @@ public LearningHubDbContextOptions Options public virtual DbSet NodeViewModel { get; set; } + /// + /// Gets or sets the CatalogueAdminViewModel. + /// + public virtual DbSet CatalogueAdminViewModel { get; set; } + /// /// Gets or sets the NodePathNodeViewModel. /// diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/LearningHub.Nhs.OpenApi.Repositories.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/LearningHub.Nhs.OpenApi.Repositories.csproj index b26c815cd..26509eb66 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/LearningHub.Nhs.OpenApi.Repositories.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/LearningHub.Nhs.OpenApi.Repositories.csproj @@ -24,6 +24,7 @@ + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Repositories/Hierarchy/CatalogueAccessRequestRepository.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Repositories/Hierarchy/CatalogueAccessRequestRepository.cs index a3b5832ba..2cef77f52 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Repositories/Hierarchy/CatalogueAccessRequestRepository.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Repositories/Hierarchy/CatalogueAccessRequestRepository.cs @@ -1,10 +1,12 @@ namespace LearningHub.Nhs.OpenApi.Repositories.Repositories.Hierarchy { using System; + using System.Collections.Generic; using System.Data; using System.Linq; using System.Threading.Tasks; using LearningHub.Nhs.Models.Entities.Hierarchy; + using LearningHub.Nhs.Models.Hierarchy; using LearningHub.Nhs.OpenApi.Repositories.EntityFramework; using LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories; using LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories.Hierarchy; @@ -75,5 +77,36 @@ public async Task CreateCatalogueAccessRequestAsync( var param6 = new SqlParameter("@p6", SqlDbType.Int) { Value = roleId }; await DbContext.Database.ExecuteSqlRawAsync("exec [hierarchy].[CatalogueAccessRequestCreate] @p0, @p1, @p2, @p3, @p4, @p5, @p6", param0, param1, param2, param3, param4, param5, param6); } + + /// + /// The GetCatalogueAdminDetailsAsync. + /// + /// The currentUserId. + /// The reference. + /// The roleId. + /// The accessType. + /// The task. + public async Task> GetCatalogueAdminDetailsAsync( + int currentUserId, + string reference, + int roleId, + string accessType) + { + try + { + var param0 = new SqlParameter("@p0", SqlDbType.Int) { Value = currentUserId }; + var param1 = new SqlParameter("@p1", SqlDbType.NVarChar) { Value = reference }; + var param2 = new SqlParameter("@p2", SqlDbType.Int) { Value = TimezoneOffsetManager.UserTimezoneOffset ?? (object)DBNull.Value }; + var param3 = new SqlParameter("@p3", SqlDbType.NVarChar) { Value = accessType }; + var param4 = new SqlParameter("@p4", SqlDbType.Int) { Value = roleId }; + ////await DbContext.Database.ExecuteSqlRawAsync("exec [hierarchy].[GetCatalogueAdminDetails] @p0, @p1, @p2, @p3, @p4", param0, param1, param2, param3, param4); + var retVal = await this.DbContext.CatalogueAdminViewModel.FromSqlRaw("hierarchy.GetCatalogueAdminDetails @p0, @p1, @p2, @p3, @p4", param0, param1, param2, param3, param4).AsNoTracking().ToListAsync(); + return retVal; + } + catch(Exception ex) + { + return null; + } + } } } diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/ICatalogueService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/ICatalogueService.cs index f763808ef..68f33b8ab 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/ICatalogueService.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/ICatalogueService.cs @@ -81,10 +81,11 @@ public interface ICatalogueService /// /// The currentUserId. /// The reference. + /// The catalogueName. /// The view model. /// The accessType. /// The bool. - Task RequestAccessAsync(int currentUserId, string reference, CatalogueAccessRequestViewModel vm, string accessType); + Task RequestAccessAsync(int currentUserId, string reference,string catalogueName, CatalogueAccessRequestViewModel vm, string accessType); /// /// The InviteUserAsync. diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/Messaging/IEmailTemplateService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/Messaging/IEmailTemplateService.cs index 7e75ae57b..b53b56cda 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/Messaging/IEmailTemplateService.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/Messaging/IEmailTemplateService.cs @@ -7,6 +7,7 @@ namespace LearningHub.Nhs.OpenApi.Services.Interface.Services.Messaging using System.Collections.Generic; using LearningHub.Nhs.Models.Email; using LearningHub.Nhs.Models.Email.Models; + using LearningHub.Nhs.Models.Entities.Messaging; /// /// The IEmailTemplateService. @@ -56,5 +57,12 @@ public interface IEmailTemplateService /// The isUserRoleUpgrade. /// The subject and body. EmailDetails GetEmailVerificationEmail(SendEmailModel emailModel, bool isUserRoleUpgrade); + + /// + /// The GetEmailTemplate. + /// + /// <The email template type id. + /// The template. + EmailTemplate GetEmailTemplateById(int emailTemplateTypeId); } } diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/Messaging/IGovMessageService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/Messaging/IGovMessageService.cs new file mode 100644 index 000000000..0de40c83e --- /dev/null +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/Messaging/IGovMessageService.cs @@ -0,0 +1,31 @@ +namespace LearningHub.Nhs.OpenApi.Services.Interface.Services.Messaging +{ + using System; + using System.Collections.Generic; + using System.Threading.Tasks; + using LearningHub.Nhs.Models.GovNotifyMessaging; + using LearningHub.Nhs.Models.Messaging; + using LearningHub.Nhs.Models.Validation; + using Microsoft.AspNetCore.Mvc; + + /// + /// The IGovMessageService interface. + /// + public interface IGovMessageService + { + /// + /// SendEmailAsync. + /// + /// the request. + /// The response. + /// The exception. + Task SendEmailAsync(EmailRequest request); + + /// + /// To queue the MessageRequests. + /// + /// The QueueRequestList. + /// The . + Task QueueRequestsAsync(QueueMessageList request); + } +} diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj index b7850fdea..5b9d9cd34 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj @@ -17,6 +17,8 @@ + + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/CatalogueService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/CatalogueService.cs index 53810f5d1..792d1e34a 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/CatalogueService.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/CatalogueService.cs @@ -14,6 +14,7 @@ using LearningHub.Nhs.Models.Entities.Hierarchy; using LearningHub.Nhs.Models.Entities.Resource; using LearningHub.Nhs.Models.Enums; + using LearningHub.Nhs.Models.GovNotifyMessaging; using LearningHub.Nhs.Models.Resource; using LearningHub.Nhs.Models.Search; using LearningHub.Nhs.Models.Validation; @@ -56,6 +57,8 @@ public class CatalogueService : ICatalogueService private readonly FindwiseConfig findwiseConfig; private readonly INotificationSenderService notificationSenderService; private readonly ITimezoneOffsetManager timezoneOffsetManager; + private readonly IGovMessageService govMessageService; + private readonly IEmailTemplateService emailTemplateService; /// /// Initializes a new instance of the class. @@ -64,20 +67,50 @@ public class CatalogueService : ICatalogueService /// /// The . /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - public CatalogueService(ICatalogueRepository catalogueRepository, INodeRepository nodeRepository, IUserUserGroupRepository userUserGroupRepository, IMapper mapper, IOptions findwiseConfig, IOptions learningHubConfig, ICatalogueNodeVersionRepository catalogueNodeVersionRepository, INodeResourceRepository nodeResourceRepository, IResourceVersionRepository resourceVersionRepository, IRoleUserGroupRepository roleUserGroupRepository, IProviderService providerService, ICatalogueAccessRequestRepository catalogueAccessRequestRepository, IUserRepository userRepository, IUserProfileRepository userProfileRepository, IEmailSenderService emailSenderService, IBookmarkRepository bookmarkRepository,INodeActivityRepository nodeActivityRepository, IFindwiseApiFacade findwiseApiFacade, INotificationSenderService notificationSenderService, ITimezoneOffsetManager timezoneOffsetManager) + /// mapper. + /// catalogueNodeVersionRepository. + /// nodeResourceRepository. + /// resourceVersionRepository. + /// roleUserGroupRepository. + /// providerService. + /// catalogueAccessRequestRepository. + /// userRepository. + /// userProfileRepository. + /// emailSenderService. + /// bookmarkRepository. + /// nodeActivityRepository. + /// findwiseApiFacade. + /// nodeRepository. + /// userUserGroupRepository. + /// findwiseConfig. + /// learningHubConfig. + /// notificationSenderService. + /// timezoneOffsetManager. + /// govMessageService. + /// emailTemplateService. + public CatalogueService( + ICatalogueRepository catalogueRepository, + INodeRepository nodeRepository, + IUserUserGroupRepository userUserGroupRepository, + IMapper mapper, + IOptions findwiseConfig, + IOptions learningHubConfig, + ICatalogueNodeVersionRepository catalogueNodeVersionRepository, + INodeResourceRepository nodeResourceRepository, + IResourceVersionRepository resourceVersionRepository, + IRoleUserGroupRepository roleUserGroupRepository, + IProviderService providerService, + ICatalogueAccessRequestRepository catalogueAccessRequestRepository, + IUserRepository userRepository, + IUserProfileRepository userProfileRepository, + IEmailSenderService emailSenderService, + IBookmarkRepository bookmarkRepository, + INodeActivityRepository nodeActivityRepository, + IFindwiseApiFacade findwiseApiFacade, + INotificationSenderService notificationSenderService, + ITimezoneOffsetManager timezoneOffsetManager, + IGovMessageService govMessageService, + IEmailTemplateService emailTemplateService) { this.catalogueRepository = catalogueRepository; this.nodeRepository = nodeRepository; @@ -99,6 +132,8 @@ public CatalogueService(ICatalogueRepository catalogueRepository, INodeRepositor this.findwiseConfig = findwiseConfig.Value; this.timezoneOffsetManager = timezoneOffsetManager; this.notificationSenderService = notificationSenderService; + this.govMessageService = govMessageService; + this.emailTemplateService = emailTemplateService; } /// @@ -387,19 +422,73 @@ public RestrictedCatalogueSummaryViewModel GetRestrictedCatalogueSummary(int cat /// /// The currentUserId. /// The reference. + /// The catalogueName. /// The view model. /// The accessType. /// The bool. - public async Task RequestAccessAsync(int currentUserId, string reference, CatalogueAccessRequestViewModel vm, string accessType) + public async Task RequestAccessAsync(int currentUserId, string reference, string catalogueName, CatalogueAccessRequestViewModel vm, string accessType) { - await this.catalogueAccessRequestRepository.CreateCatalogueAccessRequestAsync( + var emailTemplate = this.emailTemplateService.GetEmailTemplateById((int)(accessType == "access" ? EmailTemplates.CatalogueAccessRequest : EmailTemplates.CataloguePermissionRequest)); + + var catalogueAdmin = await this.catalogueAccessRequestRepository.GetCatalogueAdminDetailsAsync( currentUserId, reference, - vm.Message, vm.RoleId, - this.learningHubConfig.BaseUrl + "Catalogue/Manage/" + reference, accessType); + var personalisation = new Dictionary + { + ////["Requstername"] = vm.UserFullName, + ////["RequsterEmail"] = vm.EmailAddress, + ["name"] = vm.UserFullName, + ["catalogue name"] = catalogueName, + ["message text"] = vm.Message, + ////["Review request"] = this.learningHubConfig.BaseUrl + "Catalogue/Manage/" + reference, + }; + + // Create a list of EmailRequest objects from catalogueAdmin recipients + var queueMessage = catalogueAdmin + .Where(admin => !string.IsNullOrEmpty(admin.EmailAddress)) + .Select(admin => new QueueMessage + { + Recipient = admin.EmailAddress, + TemplateId = emailTemplate.TemplateId, + Personalisation = personalisation, + }) + .ToList(); + + if (queueMessage.Count > 0) + { + // Wrap in QueueMessageList + var queueMessageList = new QueueMessageList + { + Messages = queueMessage, + }; + + await this.govMessageService.QueueRequestsAsync(queueMessageList); + } + + ////var personalisation = new Dictionary(); + ////personalisation["name"] = vm.UserFullName; + ////personalisation["catalogue name"] = catalogueName; + ////personalisation["message text"] = vm.Message; + ////personalisation["Review request"] = this.learningHubConfig.BaseUrl + "Catalogue/Manage/" + reference; + ////var emailRequest = new EmailRequest + ////{ + //// Recipient = "swapnamol.abraham@nhs.net", + //// TemplateId = emailTemplate.TemplateId, + //// Personalisation = personalisation, + ////}; + + ////await this.govMessageService.QueueRequestsAsync(emailRequest); + + await this.catalogueAccessRequestRepository.CreateCatalogueAccessRequestAsync( + currentUserId, + reference, + vm.Message, + vm.RoleId, + this.learningHubConfig.BaseUrl + "Catalogue/Manage/" + reference, + accessType); return true; } @@ -1058,14 +1147,32 @@ await this.notificationSenderService.SendCatalogueAccessRequestRejectedNotificat $"{this.learningHubConfig.BaseUrl}Catalogue/{catalogue.Url}", responseMessage, car.UserId); - await this.emailSenderService.SendRequestAccessFailureEmail(userId, new SendEmailModel(new CatalogueAccessRequestFailureEmailModel + + ////await this.emailSenderService.SendRequestAccessFailureEmail(userId, new SendEmailModel(new CatalogueAccessRequestFailureEmailModel + ////{ + //// UserFirstName = car.UserProfile.FirstName, + //// CatalogueName = catalogue.Name, + //// RejectionReason = responseMessage, + //// CatalogueUrl = this.learningHubConfig.BaseUrl + "Catalogue/" + catalogue.Url, + ////}) + ////{ EmailAddress = car.EmailAddress }); + + var emailTemplate = this.emailTemplateService.GetEmailTemplateById((int)EmailTemplates.CatalogueAccessRequestFailure); + + var personalisation = new Dictionary(); + personalisation["name"] = car.UserProfile.FirstName + " " + car.UserProfile.LastName; + personalisation["catalogue name"] = catalogue.Name; + personalisation["reason"] = responseMessage; + + var emailRequest = new EmailRequest { - UserFirstName = car.UserProfile.FirstName, - CatalogueName = catalogue.Name, - RejectionReason = responseMessage, - CatalogueUrl = this.learningHubConfig.BaseUrl + "Catalogue/" + catalogue.Url, - }) - { EmailAddress = car.EmailAddress }); + Recipient = car.EmailAddress, + TemplateId = emailTemplate.TemplateId, + Personalisation = personalisation, + }; + + await this.govMessageService.SendEmailAsync(emailRequest); + return new LearningHubValidationResult(true); } @@ -1153,13 +1260,30 @@ await this.notificationSenderService.SendCatalogueAccessRequestAcceptedNotificat catalogue.Name, $"{this.learningHubConfig.BaseUrl}Catalogue/{catalogue.Url}", catalogueAccessRequest.UserId); - await this.emailSenderService.SendRequestAccessSuccessEmail(userId, new SendEmailModel(new CatalogueAccessRequestSuccessEmailModel + + var emailTemplate = this.emailTemplateService.GetEmailTemplateById((int)EmailTemplates.CatalogueAccessRequestSuccess); + + var personalisation = new Dictionary(); + personalisation["name"] = catalogueAccessRequest.UserProfile.FirstName + " " + catalogueAccessRequest.UserProfile.LastName; + personalisation["catalogue name"] = catalogue.Name; + + var emailRequest = new EmailRequest { - UserFirstName = catalogueAccessRequest.UserProfile.FirstName, - CatalogueName = catalogue.Name, - CatalogueUrl = $"{this.learningHubConfig.BaseUrl}Catalogue/{catalogue.Url}", - }) - { EmailAddress = catalogueAccessRequest.EmailAddress }); + Recipient = catalogueAccessRequest.EmailAddress, + TemplateId = emailTemplate.TemplateId, + Personalisation = personalisation, + }; + + await this.govMessageService.SendEmailAsync(emailRequest); + + ////await this.emailSenderService.SendRequestAccessSuccessEmail(userId, new SendEmailModel(new CatalogueAccessRequestSuccessEmailModel + ////{ + //// UserFirstName = catalogueAccessRequest.UserProfile.FirstName, + //// CatalogueName = catalogue.Name, + //// CatalogueUrl = $"{this.learningHubConfig.BaseUrl}Catalogue/{catalogue.Url}", + ////}) + ////{ EmailAddress = catalogueAccessRequest.EmailAddress }); + return new LearningHubValidationResult(true) { CreatedId = uugId }; } diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/Messaging/EmailTemplateService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/Messaging/EmailTemplateService.cs index 3f47fe35e..5396e6f32 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/Messaging/EmailTemplateService.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/Messaging/EmailTemplateService.cs @@ -8,6 +8,7 @@ using LearningHub.Nhs.Models.Enums; using LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories.Messaging; using LearningHub.Nhs.OpenApi.Services.Interface.Services.Messaging; + using EmailTemplate = Nhs.Models.Entities.Messaging.EmailTemplate; /// /// The EmailTemplateService. @@ -206,6 +207,16 @@ public EmailDetails GetEmailVerificationEmail(SendEmailModel + /// The GetEmailTemplate. + /// + /// The email template type id. + /// The template. + public EmailTemplate GetEmailTemplateById(int emailTemplateTypeId) + { + return this.emailTemplateRepository.GetTemplate(emailTemplateTypeId); + } + private string Replace(string str, Dictionary replacements) { return replacements.Aggregate( diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/Messaging/GovMessageService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/Messaging/GovMessageService.cs new file mode 100644 index 000000000..8dc82b487 --- /dev/null +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/Messaging/GovMessageService.cs @@ -0,0 +1,106 @@ +namespace LearningHub.Nhs.OpenApi.Services.Services.Messaging +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using LearningHub.Nhs.MessageQueueing.Repositories; + using LearningHub.Nhs.MessagingService.Interfaces; + using LearningHub.Nhs.Models.Entities.GovNotifyMessaging; + using LearningHub.Nhs.Models.Entities.Messaging; + using LearningHub.Nhs.Models.GovNotifyMessaging; + using LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories.Messaging; + using LearningHub.Nhs.OpenApi.Services.Interface.HttpClients; + using LearningHub.Nhs.OpenApi.Services.Interface.Services.Messaging; + using Microsoft.AspNetCore.Mvc; + using Microsoft.Extensions.Logging; + using Newtonsoft.Json; + + /// + /// The GOVMessageService class. + /// + public class GovMessageService : BaseService, IGovMessageService + { + private readonly IMessageQueueRepository messageQueueRepository; + private readonly IGovNotifyService messageService; + + /// + /// Initializes a new instance of the class. + /// + /// The findwiseHttpClient. + /// The logger. + /// The message repository. + /// The message Service. + public GovMessageService( + IFindwiseClient findwiseClient, + ILogger logger, + IMessageQueueRepository messageQueueRepository, + IGovNotifyService messageService) + : base(findwiseClient, logger) + { + this.messageQueueRepository = messageQueueRepository; + this.messageService = messageService; + } + + /// + /// SendEmailAsync + /// + /// the request. + /// The response. + /// The exception. + public async Task SendEmailAsync(EmailRequest request) + { + var response = new GovNotifyResponse(); + + if (string.IsNullOrWhiteSpace(request.Recipient) || string.IsNullOrWhiteSpace(request.TemplateId)) + { + response.IsSuccess = false; + response.ErrorMessage = "Email and template ID are required"; + return response; + } + + response = await this.messageService.SendEmailAsync(request.Recipient, request.TemplateId, request.Personalisation); + + Dictionary test = new Dictionary(); + if (response != null) + { + if (!response.IsSuccess && (request.Id == null || request.Id <= 0)) + { + var failedRequest = new SingleEmailFailedRequest + { + Recipient = request.Recipient, + TemplateId = request.TemplateId, + Personalisation = request.Personalisation != null ? JsonConvert.SerializeObject(request.Personalisation.ToDictionary(kvp => kvp.Key, kvp => kvp.Value?.ToString())) : null, + ErrorMessage = response.ErrorMessage, + }; + await this.messageQueueRepository.SaveFailedSingleEmail(failedRequest); + } + } + + return response; + } + + /// + /// To queue the MessageRequests. + /// + /// The QueueRequestList. + /// The . + public async Task QueueRequestsAsync(QueueMessageList request) + { + if (request?.Messages == null || !request.Messages.Any()) + { + throw new ArgumentException("At least one email must be provided in the request."); + } + + var requests = request.Messages.Select(q => new QueueRequests + { + Recipient = q.Recipient, + TemplateId = q.TemplateId, + Personalisation = q.Personalisation != null ? JsonConvert.SerializeObject(q.Personalisation) : null, + DeliverAfter = q.DeliverAfter ?? null, + }); + + await this.messageQueueRepository.QueueMessagesAsync(requests); + } + } +} diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Startup.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Startup.cs index 4b3bba6cc..351358704 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Startup.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Startup.cs @@ -53,6 +53,7 @@ public static void AddServices(this IServiceCollection services) services.AddScoped(); services.AddScoped(); services.AddScoped(); + services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Tests/LearningHub.Nhs.OpenApi.Tests.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Tests/LearningHub.Nhs.OpenApi.Tests.csproj index 87712e074..b6b9d99fe 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Tests/LearningHub.Nhs.OpenApi.Tests.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Tests/LearningHub.Nhs.OpenApi.Tests.csproj @@ -10,6 +10,7 @@ + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Tests/Services/Services/CatalogueServiceTests.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Tests/Services/Services/CatalogueServiceTests.cs index cfda30045..0867f0821 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Tests/Services/Services/CatalogueServiceTests.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Tests/Services/Services/CatalogueServiceTests.cs @@ -43,6 +43,8 @@ public class CatalogueServiceTests private readonly Mock> findwiseConfig; private readonly Mock notificationSenderService; private readonly Mock timezoneOffsetManager; + private readonly Mock govMessageSevice; + private readonly Mock emailTemplateService; /// /// Initializes a new instance of the class. @@ -69,7 +71,9 @@ public CatalogueServiceTests() this.findwiseConfig = new Mock>(); this.notificationSenderService = new Mock(); this.timezoneOffsetManager = new Mock(); - this.catalogueService = new CatalogueService(this.catalogueRepository.Object, this.nodeRepository.Object, this.userUserGroupRepository.Object, this.mapper.Object, this.findwiseConfig.Object, this.learningHubConfig.Object, this.catalogueNodeVersionRepository.Object, this.nodeResourceRepository.Object, this.resourceVersionRepository.Object, this.roleUserGroupRepository.Object, this.providerService.Object, this.catalogueAccessRequestRepository.Object, this.userRepository.Object, this.userProfileRepository.Object, this.emailSenderService.Object, this.bookmarkRepository.Object, this.nodeActivityRepository.Object, this.findwiseApiFacade.Object,this.notificationSenderService.Object,this.timezoneOffsetManager.Object); + this.govMessageSevice = new Mock(); + this.emailTemplateService = new Mock(); + this.catalogueService = new CatalogueService(this.catalogueRepository.Object, this.nodeRepository.Object, this.userUserGroupRepository.Object, this.mapper.Object, this.findwiseConfig.Object, this.learningHubConfig.Object, this.catalogueNodeVersionRepository.Object, this.nodeResourceRepository.Object, this.resourceVersionRepository.Object, this.roleUserGroupRepository.Object, this.providerService.Object, this.catalogueAccessRequestRepository.Object, this.userRepository.Object, this.userProfileRepository.Object, this.emailSenderService.Object, this.bookmarkRepository.Object, this.nodeActivityRepository.Object, this.findwiseApiFacade.Object, this.notificationSenderService.Object, this.timezoneOffsetManager.Object, this.govMessageSevice.Object, this.emailTemplateService.Object); } private static IEnumerable CatalogueNodeVersionList => new List() diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/CatalogueController.cs b/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/CatalogueController.cs index 55b812fdb..e5c3c090f 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/CatalogueController.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/CatalogueController.cs @@ -194,15 +194,16 @@ public async Task InviteUser(RestrictedCatalogueInviteUserViewMod /// The RequestAccess. /// /// The reference. + /// The catalogueName. /// The view model. /// The accessType. /// The ActionResult. [HttpPost] - [Route("RequestAccess/{reference}/{accessType}")] + [Route("RequestAccess/{reference}/{catalogueName}/{accessType}")] [Authorize] - public async Task RequestAccess(string reference, CatalogueAccessRequestViewModel vm, string accessType) + public async Task RequestAccess(string reference,string catalogueName, CatalogueAccessRequestViewModel vm, string accessType) { - return this.Ok(await this.catalogueService.RequestAccessAsync(this.CurrentUserId.GetValueOrDefault(), reference, vm, accessType)); + return this.Ok(await this.catalogueService.RequestAccessAsync(this.CurrentUserId.GetValueOrDefault(), reference, catalogueName, vm, accessType)); } /// diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/GovNotifyMessagingController.cs b/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/GovNotifyMessagingController.cs index 574b9dced..37b41f1cc 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/GovNotifyMessagingController.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/GovNotifyMessagingController.cs @@ -7,7 +7,10 @@ using LearningHub.Nhs.MessageQueueing.Repositories; using LearningHub.Nhs.MessagingService.Interfaces; using LearningHub.Nhs.Models.Entities.GovNotifyMessaging; + using LearningHub.Nhs.Models.Entities.Hierarchy; using LearningHub.Nhs.Models.GovNotifyMessaging; + using LearningHub.Nhs.OpenApi.Services.Interface.Services.Messaging; + using LearningHub.Nhs.OpenApi.Services.Services.Messaging; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; @@ -21,16 +24,18 @@ public class GovNotifyMessagingController : OpenApiControllerBase { private readonly IGovNotifyService messageService; private readonly IMessageQueueRepository messageQueueRepository; + private readonly IGovMessageService govMessageService; /// /// Initializes a new instance of the class. /// /// The message service. /// The email Queue Repository. - public GovNotifyMessagingController(IGovNotifyService messageService, IMessageQueueRepository messageQueueRepository) + public GovNotifyMessagingController(IGovNotifyService messageService, IMessageQueueRepository messageQueueRepository, IGovMessageService govMessageService) { this.messageService = messageService; this.messageQueueRepository = messageQueueRepository; + this.govMessageService = govMessageService; } /// @@ -44,30 +49,15 @@ public async Task SendEmailAsync([FromBody] EmailRequest request) { try { - if (string.IsNullOrWhiteSpace(request.Recipient) || string.IsNullOrWhiteSpace(request.TemplateId)) - { - return this.BadRequest("Email and template ID are required"); - } + var response = await this.govMessageService.SendEmailAsync(request); - var response = await this.messageService.SendEmailAsync(request.Recipient, request.TemplateId, request.Personalisation); - - Dictionary test = new Dictionary(); - if (response != null) + if (!response.IsSuccess) { - if (!response.IsSuccess && (request.Id == null || request.Id <= 0)) - { - var failedRequest = new SingleEmailFailedRequest - { - Recipient = request.Recipient, - TemplateId = request.TemplateId, - Personalisation = request.Personalisation != null ? JsonConvert.SerializeObject(request.Personalisation.ToDictionary(kvp => kvp.Key, kvp => kvp.Value?.ToString())) : null, - ErrorMessage = response.ErrorMessage, - }; - await this.messageQueueRepository.SaveFailedSingleEmail(failedRequest); - } + return this.BadRequest(new { error = response.ErrorMessage }); } return this.Ok(response); + } catch (Exception ex) { @@ -109,22 +99,25 @@ public async Task SendSmsAsync([FromBody] SmsRequest request) [HttpPost] public async Task QueueRequests([FromBody] QueueMessageList request) { - if (request?.Messages == null || !request.Messages.Any()) - { - return this.BadRequest("At least one email must be provided in the request."); - } + ////if (request?.Messages == null || !request.Messages.Any()) + ////{ + //// return this.BadRequest("At least one email must be provided in the request."); + ////} - var requests = request.Messages.Select(q => new QueueRequests - { - Recipient = q.Recipient, - TemplateId = q.TemplateId, - Personalisation = q.Personalisation != null ? JsonConvert.SerializeObject(q.Personalisation) : null, - DeliverAfter = q.DeliverAfter ?? null, - }); + ////var requests = request.Messages.Select(q => new QueueRequests + ////{ + //// Recipient = q.Recipient, + //// TemplateId = q.TemplateId, + //// Personalisation = q.Personalisation != null ? JsonConvert.SerializeObject(q.Personalisation) : null, + //// DeliverAfter = q.DeliverAfter ?? null, + ////}); + + ////await this.messageQueueRepository.QueueMessagesAsync(requests); + ////return this.Ok(new { Message = $"{requests.Count()} message requests queued successfully." }); - await this.messageQueueRepository.QueueMessagesAsync(requests); + await this.govMessageService.QueueRequestsAsync(request); - return this.Ok(new { Message = $"{requests.Count()} message requests queued successfully." }); + return this.Ok(new { Message = $"{request.Messages.Count} message requests queued successfully." }); } /// @@ -135,7 +128,7 @@ public async Task QueueRequests([FromBody] QueueMessageList reque [HttpGet] public async Task> PendingMessageRequests() { - return await this.messageQueueRepository.GetPendingEmailsAsync(); + return await this.messageQueueRepository.GetPendingEmailsAsync(); } /// diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj b/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj index 350c18649..9bdce4952 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj @@ -18,6 +18,7 @@ + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/Startup.cs b/OpenAPI/LearningHub.Nhs.OpenApi/Startup.cs index e76ea1c96..8ccbd6263 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi/Startup.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi/Startup.cs @@ -35,6 +35,7 @@ namespace LearningHub.NHS.OpenAPI using LearningHub.Nhs.MessagingService; using LearningHub.Nhs.MessageQueueing; using Microsoft.AspNetCore.Authentication.Cookies; + using LearningHub.Nhs.Api.Authentication; /// /// The Startup class. diff --git a/WebAPI/LearningHub.Nhs.Database/LearningHub.Nhs.Database.sqlproj b/WebAPI/LearningHub.Nhs.Database/LearningHub.Nhs.Database.sqlproj index 59f6120a2..b5e79a7bd 100644 --- a/WebAPI/LearningHub.Nhs.Database/LearningHub.Nhs.Database.sqlproj +++ b/WebAPI/LearningHub.Nhs.Database/LearningHub.Nhs.Database.sqlproj @@ -539,6 +539,9 @@ + + + diff --git a/WebAPI/LearningHub.Nhs.Database/Scripts/Post-Deploy/Scripts/UpdateEmailTemplateData.sql b/WebAPI/LearningHub.Nhs.Database/Scripts/Post-Deploy/Scripts/UpdateEmailTemplateData.sql new file mode 100644 index 000000000..5c5dff8b1 --- /dev/null +++ b/WebAPI/LearningHub.Nhs.Database/Scripts/Post-Deploy/Scripts/UpdateEmailTemplateData.sql @@ -0,0 +1,7 @@ +UPDATE [messaging].[EmailTemplate] SET TemplateId ='3c2eece7-e7aa-4966-bc6b-b4fef72ead1c' WHERE Title = 'CatalogueAccessRequest' +UPDATE [messaging].[EmailTemplate] SET TemplateId ='a8a56741-06ad-4542-a276-ea0fc3636f78' WHERE Title = 'CatalogueAccessRequestSuccess' + +UPDATE [messaging].[EmailTemplate] SET TemplateId ='81125f0f-2306-45cd-b2f6-6dc980d79e69' WHERE Title = 'CatalogueAccessRequestFailure' +UPDATE [messaging].[EmailTemplate] SET TemplateId ='f4d5bda1-8f72-4ea9-8cba-b77589b7f18e' WHERE Title = 'EmailVerified' + +UPDATE [messaging].[EmailTemplate] SET TemplateId ='c341fe2b-ca62-4af4-bea6-6c52ccfdcfe8' WHERE Title = 'EmailChangeConfirmationEmail' \ No newline at end of file diff --git a/WebAPI/LearningHub.Nhs.Database/Scripts/Pre-Deploy/Scripts/EmailTemplateTableChanges.sql b/WebAPI/LearningHub.Nhs.Database/Scripts/Pre-Deploy/Scripts/EmailTemplateTableChanges.sql new file mode 100644 index 000000000..1169c44cf --- /dev/null +++ b/WebAPI/LearningHub.Nhs.Database/Scripts/Pre-Deploy/Scripts/EmailTemplateTableChanges.sql @@ -0,0 +1,2 @@ + ALTER TABLE [messaging].[EmailTemplate] + ADD TemplateId VARCHAR(50) NULL diff --git a/WebAPI/LearningHub.Nhs.Database/Stored Procedures/Hierarchy/CatalogueAccessRequestCreate.sql b/WebAPI/LearningHub.Nhs.Database/Stored Procedures/Hierarchy/CatalogueAccessRequestCreate.sql index 98d7d5d30..ac8c5a7a9 100644 --- a/WebAPI/LearningHub.Nhs.Database/Stored Procedures/Hierarchy/CatalogueAccessRequestCreate.sql +++ b/WebAPI/LearningHub.Nhs.Database/Stored Procedures/Hierarchy/CatalogueAccessRequestCreate.sql @@ -7,6 +7,7 @@ -- -- 01-02-2021 <> Initial Revision -- 12-01-2024 Swapnamol Abraham Added Role ID referernce +-- 08-07-2025 SA GOVnotify Implementation ------------------------------------------------------------------------------- CREATE PROCEDURE [hierarchy].[CatalogueAccessRequestCreate] ( @@ -43,76 +44,76 @@ BEGIN @CurrentUserFullName = FirstName + ' ' + LastName FROM [hub].[UserProfile] where Id = @currentUserId; - DECLARE @emailTemplateBody nvarchar(max); - DECLARE @emailTemplateSubject nvarchar(max); - IF @accessType = 'access' - BEGIN - SELECT - @emailTemplateBody = REPLACE(etl.Body, '[Content]', et.Body), - @emailTemplateSubject = et.Subject - FROM - [messaging].[EmailTemplate] et - JOIN [messaging].[EmailTemplateLayout] etl on et.LayoutId = etl.Id - WHERE et.Title = 'CatalogueAccessRequest'; - END - ELSE - BEGIN - SELECT - @emailTemplateBody = REPLACE(etl.Body, '[Content]', et.Body), - @emailTemplateSubject = et.Subject - FROM - [messaging].[EmailTemplate] et - JOIN [messaging].[EmailTemplateLayout] etl on et.LayoutId = etl.Id - WHERE et.Title = 'CataloguePermissionRequest'; - END + --DECLARE @emailTemplateBody nvarchar(max); + --DECLARE @emailTemplateSubject nvarchar(max); + --IF @accessType = 'access' + --BEGIN + --SELECT + -- @emailTemplateBody = REPLACE(etl.Body, '[Content]', et.Body), + -- @emailTemplateSubject = et.Subject + --FROM + -- [messaging].[EmailTemplate] et + --JOIN [messaging].[EmailTemplateLayout] etl on et.LayoutId = etl.Id + --WHERE et.Title = 'CatalogueAccessRequest'; + --END + --ELSE + --BEGIN + --SELECT + -- @emailTemplateBody = REPLACE(etl.Body, '[Content]', et.Body), + -- @emailTemplateSubject = et.Subject + --FROM + -- [messaging].[EmailTemplate] et + --JOIN [messaging].[EmailTemplateLayout] etl on et.LayoutId = etl.Id + --WHERE et.Title = 'CataloguePermissionRequest'; + --END - DECLARE @AdminUserCursor CURSOR - SET @AdminUserCursor = CURSOR FAST_FORWARD - FOR - SELECT DISTINCT - up.FirstName as AdminFirstName, - u.Id as AdminUserId - FROM - [hub].[UserUserGroup] uug - JOIN - ( - SELECT UserGroupId FROM [hub].[RoleUserGroup] rug - JOIN [hub].[Scope] s on rug.ScopeId = s.Id - WHERE s.CatalogueNodeId = @catalogueNodeId - AND rug.RoleId = @localAdminRoleId - AND s.Deleted = 0 AND rug.Deleted = 0 - AND s.Deleted = 0 - ) arug on uug.UserGroupId = arug.UserGroupId - JOIN [hub].[User] u on u.Id = uug.UserId - JOIN [hub].[UserProfile] up on up.Id = u.Id - where uug.Deleted = 0 and u.Deleted = 0 and up.Deleted = 0; + --DECLARE @AdminUserCursor CURSOR + --SET @AdminUserCursor = CURSOR FAST_FORWARD + --FOR + --SELECT DISTINCT + -- up.FirstName as AdminFirstName, + -- u.Id as AdminUserId + --FROM + -- [hub].[UserUserGroup] uug + --JOIN + -- ( + -- SELECT UserGroupId FROM [hub].[RoleUserGroup] rug + -- JOIN [hub].[Scope] s on rug.ScopeId = s.Id + -- WHERE s.CatalogueNodeId = @catalogueNodeId + -- AND rug.RoleId = @localAdminRoleId + -- AND s.Deleted = 0 AND rug.Deleted = 0 + -- AND s.Deleted = 0 + -- ) arug on uug.UserGroupId = arug.UserGroupId + --JOIN [hub].[User] u on u.Id = uug.UserId + --JOIN [hub].[UserProfile] up on up.Id = u.Id + --where uug.Deleted = 0 and u.Deleted = 0 and up.Deleted = 0; - DECLARE @adminFirstName nvarchar(max); - DECLARE @adminUserId nvarchar(max); + --DECLARE @adminFirstName nvarchar(max); + --DECLARE @adminUserId nvarchar(max); - OPEN @AdminUserCursor; - FETCH NEXT FROM @AdminUserCursor INTO @adminFirstName, @adminUserId; + --OPEN @AdminUserCursor; + --FETCH NEXT FROM @AdminUserCursor INTO @adminFirstName, @adminUserId; - WHILE @@FETCH_STATUS = 0 - BEGIN - DECLARE @fullSubject nvarchar(max); - DECLARE @fullBody nvarchar(max); + --WHILE @@FETCH_STATUS = 0 + --BEGIN + -- DECLARE @fullSubject nvarchar(max); + -- DECLARE @fullBody nvarchar(max); - SELECT - @fullSubject = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@emailTemplateSubject, '[AdminFirstName]', @adminFirstName), '[UserEmailAddress]', @currentUserEmailAddress), '[CatalogueName]', @catalogueName), '[UserMessage]', @message), '[UserFullName]', @currentUserFullName), '[ManageAccessUrl]', @catalogueManageAccessUrl), - @fullBody = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@emailTemplateBody, '[AdminFirstName]', @adminFirstName), '[UserEmailAddress]', @currentUserEmailAddress), '[CatalogueName]', @catalogueName), '[UserMessage]', @message), '[UserFullName]', @currentUserFullName), '[ManageAccessUrl]', @catalogueManageAccessUrl); + -- SELECT + -- @fullSubject = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@emailTemplateSubject, '[AdminFirstName]', @adminFirstName), '[UserEmailAddress]', @currentUserEmailAddress), '[CatalogueName]', @catalogueName), '[UserMessage]', @message), '[UserFullName]', @currentUserFullName), '[ManageAccessUrl]', @catalogueManageAccessUrl), + -- @fullBody = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@emailTemplateBody, '[AdminFirstName]', @adminFirstName), '[UserEmailAddress]', @currentUserEmailAddress), '[CatalogueName]', @catalogueName), '[UserMessage]', @message), '[UserFullName]', @currentUserFullName), '[ManageAccessUrl]', @catalogueManageAccessUrl); - exec [messaging].[CreateEmailForUser] - @fullSubject, - @fullBody, - @adminUserId, - @currentUserId, - @UserTimezoneOffset; + -- exec [messaging].[CreateEmailForUser] + -- @fullSubject, + -- @fullBody, + -- @adminUserId, + -- @currentUserId, + -- @UserTimezoneOffset; - FETCH NEXT FROM @AdminUserCursor INTO @adminFirstName, @adminUserId; - END; - CLOSE @AdminUserCursor; - DEALLOCATE @AdminUserCursor; + -- FETCH NEXT FROM @AdminUserCursor INTO @adminFirstName, @adminUserId; + --END; + --CLOSE @AdminUserCursor; + --DEALLOCATE @AdminUserCursor; INSERT INTO [hierarchy].[CatalogueAccessRequest] (UserId, CatalogueNodeId, EmailAddress, Message, Status, Deleted, CreateUserId, CreateDate, AmendUserId, AmendDate, RoleId) diff --git a/WebAPI/LearningHub.Nhs.Database/Stored Procedures/Hierarchy/GetCatalogueAdminDetails.sql b/WebAPI/LearningHub.Nhs.Database/Stored Procedures/Hierarchy/GetCatalogueAdminDetails.sql new file mode 100644 index 000000000..a7aca6785 --- /dev/null +++ b/WebAPI/LearningHub.Nhs.Database/Stored Procedures/Hierarchy/GetCatalogueAdminDetails.sql @@ -0,0 +1,75 @@ +------------------------------------------------------------------------------- +-- Author +-- Created 28-01-2022 +-- Purpose To get the details of catalogue admin users of a catalogue. +-- +-- Modification History +-- +-- 04-07-2025 Swapnamol Abraham Initial Revision +------------------------------------------------------------------------------- +CREATE PROCEDURE [hierarchy].[GetCatalogueAdminDetails] +( + @currentUserId int, + @reference nvarchar(max), + @UserTimezoneOffset int = NULL, + @accessType nvarchar(max), + @roleId int +) +AS +BEGIN + BEGIN TRY + DECLARE @AmendDate datetimeoffset(7) = ISNULL(TODATETIMEOFFSET(DATEADD(mi, @UserTimezoneOffset, GETUTCDATE()), @UserTimezoneOffset), SYSDATETIMEOFFSET()) + + BEGIN TRAN + DECLARE @localAdminRoleId int = 3; + + DECLARE @catalogueNodeId int; + DECLARE @catalogueName nvarchar(max); + DECLARE @currentUserEmailAddress nvarchar(max); + DECLARE @currentUserFullName nvarchar(max); + SELECT + @catalogueNodeId = nv.NodeId, + @catalogueName = cnv.Name + FROM + [hierarchy].[CatalogueNodeVersion] cnv + JOIN [hierarchy].[NodeVersion] nv on cnv.NodeVersionId = nv.Id + WHERE Url = @reference AND cnv.Deleted = 0 AND nv.Deleted = 0; + + SELECT DISTINCT + up.FirstName as FirstName, + up.LastName As LastName, + up.EmailAddress AS EmailAddress, + u.Id as UserId + FROM + [hub].[UserUserGroup] uug + JOIN + ( + SELECT UserGroupId FROM [hub].[RoleUserGroup] rug + JOIN [hub].[Scope] s on rug.ScopeId = s.Id + WHERE s.CatalogueNodeId = @catalogueNodeId + AND rug.RoleId = @localAdminRoleId + AND s.Deleted = 0 AND rug.Deleted = 0 + AND s.Deleted = 0 + ) arug on uug.UserGroupId = arug.UserGroupId + JOIN [hub].[User] u on u.Id = uug.UserId + JOIN [hub].[UserProfile] up on up.Id = u.Id + where uug.Deleted = 0 and u.Deleted = 0 and up.Deleted = 0; + + END TRY + BEGIN CATCH + DECLARE @ErrorMessage NVARCHAR(4000); + DECLARE @ErrorSeverity INT; + DECLARE @ErrorState INT; + + SELECT + @ErrorMessage = ERROR_MESSAGE(), + @ErrorSeverity = ERROR_SEVERITY(), + @ErrorState = ERROR_STATE(); + + IF @@TRANCOUNT > 0 + ROLLBACK TRAN; + + RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState); + + END CATCH +END; From 19b01d8b342a2f68ab620f036a2d2884384fd058 Mon Sep 17 00:00:00 2001 From: Arunima George Date: Fri, 11 Jul 2025 10:03:12 +0100 Subject: [PATCH 06/16] TD-5790: Save Successful email transactions for One-off emails --- .../LearningHub.Nhs.AdminUI.csproj | 2 +- .../LearningHub.Nhs.WebUI.AutomatedUiTests.csproj | 2 +- LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj | 2 +- ...earningHub.Nhs.MessageQueueing.Database.sqlproj | 5 ++++- .../Scripts/Post-Deploy/Script.PostDeployment.sql | 14 ++++++++++++++ ...leEmail.sql => SaveSingleEmailTransactions.sql} | 11 ++++++----- .../EntityFramework/MessageQueueDbContext.cs | 2 -- .../LearningHub.Nhs.MessageQueueing.csproj | 2 +- .../Repositories/IMessageQueueRepository.cs | 4 ++-- .../Repositories/MessageQueueRepository.cs | 12 +++++++----- .../LearningHub.Nhs.MessagingService.csproj | 2 +- .../LearningHub.Nhs.OpenApi.Models.csproj | 2 +- ...ngHub.Nhs.OpenApi.Repositories.Interface.csproj | 2 +- .../LearningHub.Nhs.OpenApi.Repositories.csproj | 2 +- ...arningHub.Nhs.OpenApi.Services.Interface.csproj | 2 +- .../LearningHub.Nhs.OpenApi.Services.csproj | 2 +- .../Services/Messaging/GovMessageService.cs | 9 +++++---- .../LearningHub.Nhs.OpenApi.Tests.csproj | 2 +- .../LearningHub.NHS.OpenAPI.csproj | 2 +- ...ningHub.Nhs.ReportApi.Services.Interface.csproj | 2 +- ...ningHub.Nhs.ReportApi.Services.UnitTests.csproj | 2 +- .../LearningHub.Nhs.ReportApi.Services.csproj | 2 +- .../LearningHub.Nhs.ReportApi.Shared.csproj | 2 +- .../LearningHub.Nhs.ReportApi.csproj | 2 +- .../LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj | 2 +- .../LearningHub.Nhs.Api.Shared.csproj | 2 +- .../LearningHub.Nhs.Api.UnitTests.csproj | 2 +- .../LearningHub.Nhs.Repository.Interface.csproj | 2 +- .../LearningHub.Nhs.Repository.csproj | 2 +- .../LearningHub.Nhs.Services.Interface.csproj | 2 +- .../LearningHub.Nhs.Services.UnitTests.csproj | 2 +- .../LearningHub.Nhs.Services.csproj | 2 +- .../LearningHub.Nhs.Migration.ConsoleApp.csproj | 2 +- .../LearningHub.Nhs.Migration.Interface.csproj | 2 +- .../LearningHub.Nhs.Migration.Models.csproj | 2 +- ...ningHub.Nhs.Migration.Staging.Repository.csproj | 2 +- .../LearningHub.Nhs.Migration.UnitTests.csproj | 2 +- .../LearningHub.Nhs.Migration.csproj | 2 +- 38 files changed, 69 insertions(+), 50 deletions(-) create mode 100644 MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Scripts/Post-Deploy/Script.PostDeployment.sql rename MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/{SaveFailedSingleEmail.sql => SaveSingleEmailTransactions.sql} (60%) diff --git a/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj b/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj index 2038ce016..881109ae3 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj +++ b/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj @@ -89,7 +89,7 @@ - + diff --git a/LearningHub.Nhs.WebUI.AutomatedUiTests/LearningHub.Nhs.WebUI.AutomatedUiTests.csproj b/LearningHub.Nhs.WebUI.AutomatedUiTests/LearningHub.Nhs.WebUI.AutomatedUiTests.csproj index eba5ce4b4..5dbb65a58 100644 --- a/LearningHub.Nhs.WebUI.AutomatedUiTests/LearningHub.Nhs.WebUI.AutomatedUiTests.csproj +++ b/LearningHub.Nhs.WebUI.AutomatedUiTests/LearningHub.Nhs.WebUI.AutomatedUiTests.csproj @@ -12,7 +12,7 @@ - + diff --git a/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj b/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj index 7099f3b99..b69ead582 100644 --- a/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj +++ b/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj @@ -113,7 +113,7 @@ - + diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/LearningHub.Nhs.MessageQueueing.Database.sqlproj b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/LearningHub.Nhs.MessageQueueing.Database.sqlproj index 79c159525..36694de1f 100644 --- a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/LearningHub.Nhs.MessageQueueing.Database.sqlproj +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/LearningHub.Nhs.MessageQueueing.Database.sqlproj @@ -71,11 +71,14 @@ - + + + + \ No newline at end of file diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Scripts/Post-Deploy/Script.PostDeployment.sql b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Scripts/Post-Deploy/Script.PostDeployment.sql new file mode 100644 index 000000000..755411369 --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Scripts/Post-Deploy/Script.PostDeployment.sql @@ -0,0 +1,14 @@ +/* +Post-Deployment Script Template +-------------------------------------------------------------------------------------- + This file contains SQL statements that will be appended to the build script. + Use SQLCMD syntax to include a file in the post-deployment script. + Example: :r .\myfile.sql + Use SQLCMD syntax to reference a variable in the post-deployment script. + Example: :setvar TableName MyTable + SELECT * FROM [$(TableName)] +-------------------------------------------------------------------------------------- +*/ + +:r .\Scripts\RequestStatusData.sql +:r .\Scripts\RequestTypeData.sql \ No newline at end of file diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/SaveFailedSingleEmail.sql b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/SaveSingleEmailTransactions.sql similarity index 60% rename from MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/SaveFailedSingleEmail.sql rename to MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/SaveSingleEmailTransactions.sql index 32a4c6395..285c072d4 100644 --- a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/SaveFailedSingleEmail.sql +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/SaveSingleEmailTransactions.sql @@ -1,21 +1,22 @@ ------------------------------------------------------------------------------- -- Author Arunima George -- Created 27-05-2025 --- Purpose Save one-off(like otp emails) failed email request. +-- Purpose Save all one-off(like otp) email request transactions. -- -- Modification History -- -- 27-05-2025 Arunima George Initial Revision ------------------------------------------------------------------------------- -CREATE PROCEDURE [dbo].[SaveFailedSingleEmail] +CREATE PROCEDURE [dbo].[SaveSingleEmailTransactions] @Recipient nvarchar(255), @TemplateId nvarchar(50), - @Personalisation nvarchar(max), - @ErrorMessage nvarchar(max) + @Personalisation nvarchar(max) = NULL, + @Status int, + @ErrorMessage nvarchar(max) = NULL AS BEGIN insert into [dbo].[QueueRequests] (RequestTypeId, Recipient, TemplateId, Personalisation, Status, CreatedAt, LastAttemptAt,ErrorMessage ) - values (3, @Recipient, @TemplateId, @Personalisation, 3, SYSDATETIMEOFFSET(), SYSDATETIMEOFFSET(), @ErrorMessage); + values (3, @Recipient, @TemplateId, @Personalisation, @Status, SYSDATETIMEOFFSET(), SYSDATETIMEOFFSET(), @ErrorMessage); END GO diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing/EntityFramework/MessageQueueDbContext.cs b/MessageQueueing/LearningHub.Nhs.MessageQueueing/EntityFramework/MessageQueueDbContext.cs index 5b392c8d6..f6c1d5870 100644 --- a/MessageQueueing/LearningHub.Nhs.MessageQueueing/EntityFramework/MessageQueueDbContext.cs +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing/EntityFramework/MessageQueueDbContext.cs @@ -31,8 +31,6 @@ public MessageQueueDbContextOptions Options get { return this.options; } } - ////public virtual DbSet QueueRequests { get; set; } - /// /// Gets or sets the PendingMessageRequests. /// diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing/LearningHub.Nhs.MessageQueueing.csproj b/MessageQueueing/LearningHub.Nhs.MessageQueueing/LearningHub.Nhs.MessageQueueing.csproj index 1d7e25a32..65f77786e 100644 --- a/MessageQueueing/LearningHub.Nhs.MessageQueueing/LearningHub.Nhs.MessageQueueing.csproj +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing/LearningHub.Nhs.MessageQueueing.csproj @@ -7,7 +7,7 @@ - + diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/IMessageQueueRepository.cs b/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/IMessageQueueRepository.cs index 110343012..825b61972 100644 --- a/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/IMessageQueueRepository.cs +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/IMessageQueueRepository.cs @@ -38,10 +38,10 @@ public interface IMessageQueueRepository Task MessageDeliverySuccess(GovNotifyResponse response); /// - /// Save failed one-off email. + /// Save one-off emails. /// /// The email request. /// The . - Task SaveFailedSingleEmail(SingleEmailFailedRequest request); + Task SaveSingleEmailTransactions(SingleEmailRequest request); } } diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/MessageQueueRepository.cs b/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/MessageQueueRepository.cs index 8e5059bd6..2089c41fa 100644 --- a/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/MessageQueueRepository.cs +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/MessageQueueRepository.cs @@ -1,5 +1,6 @@ namespace LearningHub.Nhs.MessageQueueing.Repositories { + using System; using System.Collections.Generic; using System.Data; using System.Threading.Tasks; @@ -74,17 +75,18 @@ public async Task MessageDeliveryFailed(GovNotifyResponse response) } /// - /// The Save failed Single Emails. + /// The Save Single Emails. /// /// The request. /// The . - public async Task SaveFailedSingleEmail(SingleEmailFailedRequest request) + public async Task SaveSingleEmailTransactions(SingleEmailRequest request) { var param0 = new SqlParameter("@p0", SqlDbType.NVarChar) { Value = request.Recipient }; var param1 = new SqlParameter("@p1", SqlDbType.NVarChar) { Value = request.TemplateId }; - var param2 = new SqlParameter("@p2", SqlDbType.NVarChar) { Value = request.Personalisation }; - var param3 = new SqlParameter("@p3", SqlDbType.NVarChar) { Value = request.ErrorMessage }; - await this.dbContext.Database.ExecuteSqlRawAsync("dbo.SaveFailedSingleEmail @p0, @p1, @p2, @p3", param0, param1, param2, param3); + var param2 = new SqlParameter("@p2", SqlDbType.NVarChar) { Value = request.Personalisation == null ? DBNull.Value : request.Personalisation }; + var param3 = new SqlParameter("@p3", SqlDbType.Int) { Value = request.Status }; + var param4 = new SqlParameter("@p4", SqlDbType.NVarChar) { Value = request.ErrorMessage == null ? DBNull.Value : request.ErrorMessage }; + await this.dbContext.Database.ExecuteSqlRawAsync("dbo.SaveSingleEmailTransactions @p0, @p1, @p2, @p3, @p4", param0, param1, param2, param3, param4); } } } diff --git a/MessagingService/LearningHub.Nhs.MessagingService/LearningHub.Nhs.MessagingService.csproj b/MessagingService/LearningHub.Nhs.MessagingService/LearningHub.Nhs.MessagingService.csproj index bd12f3577..356759ba9 100644 --- a/MessagingService/LearningHub.Nhs.MessagingService/LearningHub.Nhs.MessagingService.csproj +++ b/MessagingService/LearningHub.Nhs.MessagingService/LearningHub.Nhs.MessagingService.csproj @@ -8,7 +8,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Models/LearningHub.Nhs.OpenApi.Models.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Models/LearningHub.Nhs.OpenApi.Models.csproj index a4341e802..a0b5ee15d 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Models/LearningHub.Nhs.OpenApi.Models.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Models/LearningHub.Nhs.OpenApi.Models.csproj @@ -16,7 +16,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/LearningHub.Nhs.OpenApi.Repositories.Interface.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/LearningHub.Nhs.OpenApi.Repositories.Interface.csproj index 61795062e..2ac5c4614 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/LearningHub.Nhs.OpenApi.Repositories.Interface.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/LearningHub.Nhs.OpenApi.Repositories.Interface.csproj @@ -17,7 +17,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/LearningHub.Nhs.OpenApi.Repositories.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/LearningHub.Nhs.OpenApi.Repositories.csproj index 26509eb66..b3ba14fd0 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/LearningHub.Nhs.OpenApi.Repositories.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/LearningHub.Nhs.OpenApi.Repositories.csproj @@ -24,7 +24,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/LearningHub.Nhs.OpenApi.Services.Interface.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/LearningHub.Nhs.OpenApi.Services.Interface.csproj index d3907645f..8e13ee4da 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/LearningHub.Nhs.OpenApi.Services.Interface.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/LearningHub.Nhs.OpenApi.Services.Interface.csproj @@ -17,7 +17,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj index 5b9d9cd34..645a11add 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj @@ -32,7 +32,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/Messaging/GovMessageService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/Messaging/GovMessageService.cs index 8dc82b487..0428df905 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/Messaging/GovMessageService.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/Messaging/GovMessageService.cs @@ -8,6 +8,7 @@ using LearningHub.Nhs.MessagingService.Interfaces; using LearningHub.Nhs.Models.Entities.GovNotifyMessaging; using LearningHub.Nhs.Models.Entities.Messaging; + using LearningHub.Nhs.Models.Enums.GovNotifyMessaging; using LearningHub.Nhs.Models.GovNotifyMessaging; using LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories.Messaging; using LearningHub.Nhs.OpenApi.Services.Interface.HttpClients; @@ -61,19 +62,19 @@ public async Task SendEmailAsync(EmailRequest request) response = await this.messageService.SendEmailAsync(request.Recipient, request.TemplateId, request.Personalisation); - Dictionary test = new Dictionary(); if (response != null) { - if (!response.IsSuccess && (request.Id == null || request.Id <= 0)) + if (request.Id == null || request.Id <= 0) { - var failedRequest = new SingleEmailFailedRequest + var emailRequest = new SingleEmailRequest { Recipient = request.Recipient, TemplateId = request.TemplateId, Personalisation = request.Personalisation != null ? JsonConvert.SerializeObject(request.Personalisation.ToDictionary(kvp => kvp.Key, kvp => kvp.Value?.ToString())) : null, + Status = response.IsSuccess == true ? RequestStatusEnum.Sent : RequestStatusEnum.Failed, ErrorMessage = response.ErrorMessage, }; - await this.messageQueueRepository.SaveFailedSingleEmail(failedRequest); + await this.messageQueueRepository.SaveSingleEmailTransactions(emailRequest); } } diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Tests/LearningHub.Nhs.OpenApi.Tests.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Tests/LearningHub.Nhs.OpenApi.Tests.csproj index b6b9d99fe..ef45cc84e 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Tests/LearningHub.Nhs.OpenApi.Tests.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Tests/LearningHub.Nhs.OpenApi.Tests.csproj @@ -10,7 +10,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj b/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj index 9bdce4952..056a08a6a 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj @@ -18,7 +18,7 @@ - + diff --git a/ReportAPI/LearningHub.Nhs.ReportApi.Services.Interface/LearningHub.Nhs.ReportApi.Services.Interface.csproj b/ReportAPI/LearningHub.Nhs.ReportApi.Services.Interface/LearningHub.Nhs.ReportApi.Services.Interface.csproj index 655caa351..4d4b78635 100644 --- a/ReportAPI/LearningHub.Nhs.ReportApi.Services.Interface/LearningHub.Nhs.ReportApi.Services.Interface.csproj +++ b/ReportAPI/LearningHub.Nhs.ReportApi.Services.Interface/LearningHub.Nhs.ReportApi.Services.Interface.csproj @@ -16,7 +16,7 @@ - + diff --git a/ReportAPI/LearningHub.Nhs.ReportApi.Services.UnitTests/LearningHub.Nhs.ReportApi.Services.UnitTests.csproj b/ReportAPI/LearningHub.Nhs.ReportApi.Services.UnitTests/LearningHub.Nhs.ReportApi.Services.UnitTests.csproj index 537f585bd..26d8dd4c5 100644 --- a/ReportAPI/LearningHub.Nhs.ReportApi.Services.UnitTests/LearningHub.Nhs.ReportApi.Services.UnitTests.csproj +++ b/ReportAPI/LearningHub.Nhs.ReportApi.Services.UnitTests/LearningHub.Nhs.ReportApi.Services.UnitTests.csproj @@ -18,7 +18,7 @@ - + diff --git a/ReportAPI/LearningHub.Nhs.ReportApi.Services/LearningHub.Nhs.ReportApi.Services.csproj b/ReportAPI/LearningHub.Nhs.ReportApi.Services/LearningHub.Nhs.ReportApi.Services.csproj index 42d7766fc..351f129fe 100644 --- a/ReportAPI/LearningHub.Nhs.ReportApi.Services/LearningHub.Nhs.ReportApi.Services.csproj +++ b/ReportAPI/LearningHub.Nhs.ReportApi.Services/LearningHub.Nhs.ReportApi.Services.csproj @@ -19,7 +19,7 @@ - + diff --git a/ReportAPI/LearningHub.Nhs.ReportApi.Shared/LearningHub.Nhs.ReportApi.Shared.csproj b/ReportAPI/LearningHub.Nhs.ReportApi.Shared/LearningHub.Nhs.ReportApi.Shared.csproj index 5b6a9d92e..7301746ca 100644 --- a/ReportAPI/LearningHub.Nhs.ReportApi.Shared/LearningHub.Nhs.ReportApi.Shared.csproj +++ b/ReportAPI/LearningHub.Nhs.ReportApi.Shared/LearningHub.Nhs.ReportApi.Shared.csproj @@ -17,7 +17,7 @@ - + diff --git a/ReportAPI/LearningHub.Nhs.ReportApi/LearningHub.Nhs.ReportApi.csproj b/ReportAPI/LearningHub.Nhs.ReportApi/LearningHub.Nhs.ReportApi.csproj index b215db06c..1accacfdf 100644 --- a/ReportAPI/LearningHub.Nhs.ReportApi/LearningHub.Nhs.ReportApi.csproj +++ b/ReportAPI/LearningHub.Nhs.ReportApi/LearningHub.Nhs.ReportApi.csproj @@ -20,7 +20,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj b/WebAPI/LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj index 983fb9d8a..5b314cc3f 100644 --- a/WebAPI/LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj +++ b/WebAPI/LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj @@ -29,7 +29,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Api.Shared/LearningHub.Nhs.Api.Shared.csproj b/WebAPI/LearningHub.Nhs.Api.Shared/LearningHub.Nhs.Api.Shared.csproj index 8173a68b2..88a245e92 100644 --- a/WebAPI/LearningHub.Nhs.Api.Shared/LearningHub.Nhs.Api.Shared.csproj +++ b/WebAPI/LearningHub.Nhs.Api.Shared/LearningHub.Nhs.Api.Shared.csproj @@ -9,7 +9,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/WebAPI/LearningHub.Nhs.Api.UnitTests/LearningHub.Nhs.Api.UnitTests.csproj b/WebAPI/LearningHub.Nhs.Api.UnitTests/LearningHub.Nhs.Api.UnitTests.csproj index ca8916c4e..39a60d1a1 100644 --- a/WebAPI/LearningHub.Nhs.Api.UnitTests/LearningHub.Nhs.Api.UnitTests.csproj +++ b/WebAPI/LearningHub.Nhs.Api.UnitTests/LearningHub.Nhs.Api.UnitTests.csproj @@ -11,7 +11,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Repository.Interface/LearningHub.Nhs.Repository.Interface.csproj b/WebAPI/LearningHub.Nhs.Repository.Interface/LearningHub.Nhs.Repository.Interface.csproj index 1c2dfe61b..0a9e8972c 100644 --- a/WebAPI/LearningHub.Nhs.Repository.Interface/LearningHub.Nhs.Repository.Interface.csproj +++ b/WebAPI/LearningHub.Nhs.Repository.Interface/LearningHub.Nhs.Repository.Interface.csproj @@ -10,7 +10,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Repository/LearningHub.Nhs.Repository.csproj b/WebAPI/LearningHub.Nhs.Repository/LearningHub.Nhs.Repository.csproj index a84412769..d3a624988 100644 --- a/WebAPI/LearningHub.Nhs.Repository/LearningHub.Nhs.Repository.csproj +++ b/WebAPI/LearningHub.Nhs.Repository/LearningHub.Nhs.Repository.csproj @@ -9,7 +9,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Services.Interface/LearningHub.Nhs.Services.Interface.csproj b/WebAPI/LearningHub.Nhs.Services.Interface/LearningHub.Nhs.Services.Interface.csproj index c76a6ee5c..03d5daf03 100644 --- a/WebAPI/LearningHub.Nhs.Services.Interface/LearningHub.Nhs.Services.Interface.csproj +++ b/WebAPI/LearningHub.Nhs.Services.Interface/LearningHub.Nhs.Services.Interface.csproj @@ -16,7 +16,7 @@ - + all diff --git a/WebAPI/LearningHub.Nhs.Services.UnitTests/LearningHub.Nhs.Services.UnitTests.csproj b/WebAPI/LearningHub.Nhs.Services.UnitTests/LearningHub.Nhs.Services.UnitTests.csproj index 06af56b2a..1f246a2cd 100644 --- a/WebAPI/LearningHub.Nhs.Services.UnitTests/LearningHub.Nhs.Services.UnitTests.csproj +++ b/WebAPI/LearningHub.Nhs.Services.UnitTests/LearningHub.Nhs.Services.UnitTests.csproj @@ -13,7 +13,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Services/LearningHub.Nhs.Services.csproj b/WebAPI/LearningHub.Nhs.Services/LearningHub.Nhs.Services.csproj index 903884270..72455e02f 100644 --- a/WebAPI/LearningHub.Nhs.Services/LearningHub.Nhs.Services.csproj +++ b/WebAPI/LearningHub.Nhs.Services/LearningHub.Nhs.Services.csproj @@ -13,7 +13,7 @@ - + diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.ConsoleApp/LearningHub.Nhs.Migration.ConsoleApp.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.ConsoleApp/LearningHub.Nhs.Migration.ConsoleApp.csproj index 3119248d5..8d185ab26 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.ConsoleApp/LearningHub.Nhs.Migration.ConsoleApp.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.ConsoleApp/LearningHub.Nhs.Migration.ConsoleApp.csproj @@ -25,7 +25,7 @@ - + all diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Interface/LearningHub.Nhs.Migration.Interface.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Interface/LearningHub.Nhs.Migration.Interface.csproj index bc30ad48a..d7b8577be 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Interface/LearningHub.Nhs.Migration.Interface.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Interface/LearningHub.Nhs.Migration.Interface.csproj @@ -9,7 +9,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Models/LearningHub.Nhs.Migration.Models.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Models/LearningHub.Nhs.Migration.Models.csproj index 5ab9d00b1..891cacecf 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Models/LearningHub.Nhs.Migration.Models.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Models/LearningHub.Nhs.Migration.Models.csproj @@ -10,7 +10,7 @@ - + all diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Staging.Repository/LearningHub.Nhs.Migration.Staging.Repository.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Staging.Repository/LearningHub.Nhs.Migration.Staging.Repository.csproj index 539446335..0026cd91f 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Staging.Repository/LearningHub.Nhs.Migration.Staging.Repository.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Staging.Repository/LearningHub.Nhs.Migration.Staging.Repository.csproj @@ -9,7 +9,7 @@ - + diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.UnitTests/LearningHub.Nhs.Migration.UnitTests.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.UnitTests/LearningHub.Nhs.Migration.UnitTests.csproj index 693ef008d..02b1be10f 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.UnitTests/LearningHub.Nhs.Migration.UnitTests.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.UnitTests/LearningHub.Nhs.Migration.UnitTests.csproj @@ -10,7 +10,7 @@ - + diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration/LearningHub.Nhs.Migration.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration/LearningHub.Nhs.Migration.csproj index a184bb27f..defd79549 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration/LearningHub.Nhs.Migration.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration/LearningHub.Nhs.Migration.csproj @@ -12,7 +12,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive From ea5bc0cfe501ade03003754b955da41c194f5302 Mon Sep 17 00:00:00 2001 From: swapnamol-abraham Date: Fri, 11 Jul 2025 15:16:21 +0100 Subject: [PATCH 07/16] TD-5736: Implemented the Invite user and catalogue permission request templates --- .../Services/CatalogueService.cs | 113 +++++++++--------- 1 file changed, 55 insertions(+), 58 deletions(-) diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/CatalogueService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/CatalogueService.cs index 792d1e34a..66b3a4965 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/CatalogueService.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/CatalogueService.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Linq; + using System.Runtime.ConstrainedExecution; using System.Threading.Tasks; using AutoMapper; using LearningHub.Nhs.Models.Catalogue; @@ -430,65 +431,43 @@ public async Task RequestAccessAsync(int currentUserId, string reference, { var emailTemplate = this.emailTemplateService.GetEmailTemplateById((int)(accessType == "access" ? EmailTemplates.CatalogueAccessRequest : EmailTemplates.CataloguePermissionRequest)); - var catalogueAdmin = await this.catalogueAccessRequestRepository.GetCatalogueAdminDetailsAsync( - currentUserId, - reference, - vm.RoleId, - accessType); + var catalogueAdmin = await this.catalogueAccessRequestRepository.GetCatalogueAdminDetailsAsync(currentUserId, reference, vm.RoleId, accessType); - var personalisation = new Dictionary - { - ////["Requstername"] = vm.UserFullName, - ////["RequsterEmail"] = vm.EmailAddress, - ["name"] = vm.UserFullName, - ["catalogue name"] = catalogueName, - ["message text"] = vm.Message, - ////["Review request"] = this.learningHubConfig.BaseUrl + "Catalogue/Manage/" + reference, - }; - - // Create a list of EmailRequest objects from catalogueAdmin recipients - var queueMessage = catalogueAdmin + var queueMessages = catalogueAdmin .Where(admin => !string.IsNullOrEmpty(admin.EmailAddress)) .Select(admin => new QueueMessage { Recipient = admin.EmailAddress, TemplateId = emailTemplate.TemplateId, - Personalisation = personalisation, + Personalisation = new Dictionary + { + ["catalogue admin name"] = admin.FirstName, + ["name"] = vm.UserFullName, + ["email"] = vm.EmailAddress, + ["catalogue name"] = catalogueName, + ["message text"] = vm.Message, + ["Review request url"] = this.learningHubConfig.BaseUrl + "Catalogue/Manage/" + reference, + }, }) .ToList(); - if (queueMessage.Count > 0) + if (queueMessages.Count > 0) { - // Wrap in QueueMessageList var queueMessageList = new QueueMessageList { - Messages = queueMessage, + Messages = queueMessages, }; await this.govMessageService.QueueRequestsAsync(queueMessageList); } - ////var personalisation = new Dictionary(); - ////personalisation["name"] = vm.UserFullName; - ////personalisation["catalogue name"] = catalogueName; - ////personalisation["message text"] = vm.Message; - ////personalisation["Review request"] = this.learningHubConfig.BaseUrl + "Catalogue/Manage/" + reference; - ////var emailRequest = new EmailRequest - ////{ - //// Recipient = "swapnamol.abraham@nhs.net", - //// TemplateId = emailTemplate.TemplateId, - //// Personalisation = personalisation, - ////}; - - ////await this.govMessageService.QueueRequestsAsync(emailRequest); - await this.catalogueAccessRequestRepository.CreateCatalogueAccessRequestAsync( - currentUserId, - reference, - vm.Message, - vm.RoleId, - this.learningHubConfig.BaseUrl + "Catalogue/Manage/" + reference, - accessType); + currentUserId, + reference, + vm.Message, + vm.RoleId, + this.learningHubConfig.BaseUrl + "Catalogue/Manage/" + reference, + accessType); return true; } @@ -503,24 +482,40 @@ public async Task InviteUserAsync(int currentUserId, RestrictedCatalogueIn var catalogue = this.catalogueNodeVersionRepository.GetBasicCatalogue(vm.CatalogueNodeId); var user = await this.userProfileRepository.GetByIdAsync(currentUserId); var invitedUser = await this.userProfileRepository.GetByEmailAddressAsync(vm.EmailAddress); - var greeting = "Hi there"; - if (invitedUser != null) + ////var greeting = "Hi there"; + ////if (invitedUser != null) + ////{ + //// greeting = $"Dear {invitedUser.FirstName}"; + ////} + + ////var emailModel = new SendEmailModel( + //// new CatalogueAccessInviteEmailModel + //// { + //// CatalogueName = catalogue.Name, + //// CatalogueUrl = $"{this.learningHubConfig.BaseUrl}Catalogue/{catalogue.Url}", + //// AdminFullName = $"{user.FirstName} {user.LastName}", + //// CreateAccountUrl = $"{this.learningHubConfig.BaseUrl}Registration/create-an-account", + //// Greeting = greeting, + //// }); + ////emailModel.EmailAddress = vm.EmailAddress; + ////await this.emailSenderService.SendAccessRequestInviteEmail(currentUserId, emailModel); + + var emailTemplate = this.emailTemplateService.GetEmailTemplateById((int)EmailTemplates.CatalogueAccessInvitation); + + var personalisation = new Dictionary(); + personalisation["name"] = user.FirstName; + personalisation["catalogue name"] = catalogue.Name; + personalisation["catalogue name url"] = $"{this.learningHubConfig.BaseUrl}Catalogue/{catalogue.Url}"; + + var emailRequest = new EmailRequest { - greeting = $"Dear {invitedUser.FirstName}"; - } + Recipient = vm.EmailAddress, + TemplateId = emailTemplate.TemplateId, + Personalisation = personalisation, + }; - var emailModel = new SendEmailModel( - new CatalogueAccessInviteEmailModel - { - CatalogueName = catalogue.Name, - CatalogueUrl = $"{this.learningHubConfig.BaseUrl}Catalogue/{catalogue.Url}", - AdminFullName = $"{user.FirstName} {user.LastName}", - CreateAccountUrl = $"{this.learningHubConfig.BaseUrl}Registration/create-an-account", - Greeting = greeting, - }); - emailModel.EmailAddress = vm.EmailAddress; + await this.govMessageService.SendEmailAsync(emailRequest); - await this.emailSenderService.SendAccessRequestInviteEmail(currentUserId, emailModel); return true; } @@ -1160,8 +1155,9 @@ await this.notificationSenderService.SendCatalogueAccessRequestRejectedNotificat var emailTemplate = this.emailTemplateService.GetEmailTemplateById((int)EmailTemplates.CatalogueAccessRequestFailure); var personalisation = new Dictionary(); - personalisation["name"] = car.UserProfile.FirstName + " " + car.UserProfile.LastName; + personalisation["name"] = car.UserProfile.FirstName; personalisation["catalogue name"] = catalogue.Name; + personalisation["catalogue name url"] = $"{this.learningHubConfig.BaseUrl}Catalogue/{catalogue.Url}"; personalisation["reason"] = responseMessage; var emailRequest = new EmailRequest @@ -1264,8 +1260,9 @@ await this.notificationSenderService.SendCatalogueAccessRequestAcceptedNotificat var emailTemplate = this.emailTemplateService.GetEmailTemplateById((int)EmailTemplates.CatalogueAccessRequestSuccess); var personalisation = new Dictionary(); - personalisation["name"] = catalogueAccessRequest.UserProfile.FirstName + " " + catalogueAccessRequest.UserProfile.LastName; + personalisation["name"] = catalogueAccessRequest.UserProfile.FirstName; personalisation["catalogue name"] = catalogue.Name; + personalisation["catalogue name url"] = $"{this.learningHubConfig.BaseUrl}Catalogue/{catalogue.Url}"; var emailRequest = new EmailRequest { From 4ff2d676b7bcff5e9668c67882baf1e4d4973509 Mon Sep 17 00:00:00 2001 From: swapnamol-abraham Date: Fri, 11 Jul 2025 15:19:59 +0100 Subject: [PATCH 08/16] TD-5736: Template data updaated --- .../Scripts/UpdateEmailTemplateData.sql | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/WebAPI/LearningHub.Nhs.Database/Scripts/Post-Deploy/Scripts/UpdateEmailTemplateData.sql b/WebAPI/LearningHub.Nhs.Database/Scripts/Post-Deploy/Scripts/UpdateEmailTemplateData.sql index 5c5dff8b1..179343934 100644 --- a/WebAPI/LearningHub.Nhs.Database/Scripts/Post-Deploy/Scripts/UpdateEmailTemplateData.sql +++ b/WebAPI/LearningHub.Nhs.Database/Scripts/Post-Deploy/Scripts/UpdateEmailTemplateData.sql @@ -1,7 +1,20 @@ UPDATE [messaging].[EmailTemplate] SET TemplateId ='3c2eece7-e7aa-4966-bc6b-b4fef72ead1c' WHERE Title = 'CatalogueAccessRequest' +GO + UPDATE [messaging].[EmailTemplate] SET TemplateId ='a8a56741-06ad-4542-a276-ea0fc3636f78' WHERE Title = 'CatalogueAccessRequestSuccess' +GO UPDATE [messaging].[EmailTemplate] SET TemplateId ='81125f0f-2306-45cd-b2f6-6dc980d79e69' WHERE Title = 'CatalogueAccessRequestFailure' +GO + UPDATE [messaging].[EmailTemplate] SET TemplateId ='f4d5bda1-8f72-4ea9-8cba-b77589b7f18e' WHERE Title = 'EmailVerified' +GO + +UPDATE [messaging].[EmailTemplate] SET TemplateId ='c341fe2b-ca62-4af4-bea6-6c52ccfdcfe8' WHERE Title = 'EmailChangeConfirmationEmail' +GO + +UPDATE [messaging].[EmailTemplate] SET TemplateId ='0e7e0333-cf64-4461-b828-2a8c6c339207' WHERE Title = 'CataloguePermissionRequest' +Go -UPDATE [messaging].[EmailTemplate] SET TemplateId ='c341fe2b-ca62-4af4-bea6-6c52ccfdcfe8' WHERE Title = 'EmailChangeConfirmationEmail' \ No newline at end of file +UPDATE [messaging].[EmailTemplate] SET TemplateId ='e6d981d1-f6b2-4a17-8caa-f727e1b4f445' WHERE Title = 'CatalogueAccessInvitation' +GO \ No newline at end of file From 764fe3234108837e66c573902038f52d579bdd13 Mon Sep 17 00:00:00 2001 From: Arunima George Date: Mon, 14 Jul 2025 16:19:53 +0100 Subject: [PATCH 09/16] TD-5814: Replaced the SMTP notification with GovNotify in Full user upgrade. --- .../Services/SecurityService.cs | 51 +++++++++++++++++-- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/SecurityService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/SecurityService.cs index 1f87cdc17..58d7e0436 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/SecurityService.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/SecurityService.cs @@ -1,6 +1,7 @@ namespace LearningHub.Nhs.OpenApi.Services.Services { using System; + using System.Collections.Generic; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; @@ -11,6 +12,7 @@ using LearningHub.Nhs.Models.Email.Models; using LearningHub.Nhs.Models.Entities; using LearningHub.Nhs.Models.Enums; + using LearningHub.Nhs.Models.GovNotifyMessaging; using LearningHub.Nhs.OpenApi.Models.Configuration; using LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories; using LearningHub.Nhs.OpenApi.Services.Interface.Services; @@ -28,6 +30,9 @@ public class SecurityService : ISecurityService private readonly IEmailChangeValidationTokenRepository emailChangeValidationTokenRepository; private readonly IEmailSenderService emailSenderService; private readonly LearningHubConfig learningHubConfig; + private readonly IGovMessageService govMessageService; + private readonly IEmailTemplateService emailTemplateService; + private readonly IUserProfileRepository userProfileRepository; /// /// Initializes a new instance of the class. @@ -35,14 +40,23 @@ public class SecurityService : ISecurityService /// emailChangeValidationTokenRepository. /// emailSenderService. /// settings. + /// govMessageService. + /// emailTemplateService. + /// userProfileRepository. public SecurityService( IEmailChangeValidationTokenRepository emailChangeValidationTokenRepository, IEmailSenderService emailSenderService, - IOptions learningHubConfig) + IOptions learningHubConfig, + IGovMessageService govMessageService, + IEmailTemplateService emailTemplateService, + IUserProfileRepository userProfileRepository) { this.emailChangeValidationTokenRepository = emailChangeValidationTokenRepository; this.emailSenderService = emailSenderService; this.learningHubConfig = learningHubConfig.Value; + this.govMessageService = govMessageService; + this.emailTemplateService = emailTemplateService; + this.userProfileRepository = userProfileRepository; } /// @@ -74,7 +88,24 @@ public async Task GenerateEmailChangeValidationTokenAndSendEmail(int userId, str }; var validateTokenUrl = $"{this.learningHubConfig.BaseUrl}confirm-email?token={HttpUtility.UrlEncode(userToken)}&loctoken={HttpUtility.UrlEncode(lookupToken)}"; - await SendEmailChangeConfirmationEmail(userId, email, validateTokenUrl, isUserRoleUpgrade); + var user = await this.userProfileRepository.GetByIdAsync(userId); + var emailTemplate = this.emailTemplateService.GetEmailTemplateById((int)EmailTemplates.EmailChangeConfirmationEmail); + var personalisation = new Dictionary(); + personalisation["user name"] = user.UserName; + personalisation["confirm_email_link"] = validateTokenUrl; + personalisation["date"] = emailChangeValidationToken.Expiry.ToString("dd-MM-yyyy"); + personalisation["time"] = emailChangeValidationToken.Expiry.ToString("HH:mm"); + + var emailRequest = new EmailRequest + { + Recipient = email, + TemplateId = emailTemplate.TemplateId, + Personalisation = personalisation, + }; + + await this.govMessageService.SendEmailAsync(emailRequest); + + ////await SendEmailChangeConfirmationEmail(userId, email, validateTokenUrl, isUserRoleUpgrade); await emailChangeValidationTokenRepository.CreateAsync(userId, emailChangeValidationToken); } @@ -127,7 +158,21 @@ public async Task ValidateEmailChangeTokenAsyn tokenResult.Email = emailChangeValidationToken.Email; tokenResult.UserId = emailChangeValidationToken.UserId; tokenResult.Valid = true; - await this.SendEmailAfterEmailVerification(emailChangeValidationToken.UserId, emailChangeValidationToken.Email, isUserRoleUpgrade); + + var emailTemplate = this.emailTemplateService.GetEmailTemplateById((int)EmailTemplates.EmailVerified); + var personalisation = new Dictionary(); + personalisation["user name"] = emailChangeValidationToken.User.UserName; + + var emailRequest = new EmailRequest + { + Recipient = emailChangeValidationToken.Email, + TemplateId = emailTemplate.TemplateId, + Personalisation = personalisation, + }; + + await this.govMessageService.SendEmailAsync(emailRequest); + + ////await this.SendEmailAfterEmailVerification(emailChangeValidationToken.UserId, emailChangeValidationToken.Email, isUserRoleUpgrade); } } From 9426f30e4a49f79ced1980db1029066c039cdd7e Mon Sep 17 00:00:00 2001 From: Arunima George Date: Tue, 15 Jul 2025 11:28:44 +0100 Subject: [PATCH 10/16] Added Not Exists condition in sql data queries. --- .../Post-Deploy/Scripts/RequestStatusData.sql | 16 ++++++++++++---- .../Post-Deploy/Scripts/RequestTypeData.sql | 16 ++++++++++++---- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Scripts/Post-Deploy/Scripts/RequestStatusData.sql b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Scripts/Post-Deploy/Scripts/RequestStatusData.sql index d09b31f81..3171b73fd 100644 --- a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Scripts/Post-Deploy/Scripts/RequestStatusData.sql +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Scripts/Post-Deploy/Scripts/RequestStatusData.sql @@ -1,6 +1,14 @@ -INSERT [dbo].[RequestStatus] ([Id], [RequestStatus]) VALUES (1, N'Pending') -GO +IF NOT EXISTS(SELECT Id FROM [dbo].[RequestStatus] WHERE Id = 1) +BEGIN +INSERT [dbo].[RequestStatus] ([Id], [RequestStatus]) VALUES (1, N'Pending') +END + +IF NOT EXISTS(SELECT Id FROM [dbo].[RequestStatus] WHERE Id = 2) +BEGIN INSERT [dbo].[RequestStatus] ([Id], [RequestStatus]) VALUES (2, N'Sent') -GO +END + +IF NOT EXISTS(SELECT Id FROM [dbo].[RequestStatus] WHERE Id = 3) +BEGIN INSERT [dbo].[RequestStatus] ([Id], [RequestStatus]) VALUES (3, N'Failed') -GO \ No newline at end of file +END \ No newline at end of file diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Scripts/Post-Deploy/Scripts/RequestTypeData.sql b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Scripts/Post-Deploy/Scripts/RequestTypeData.sql index a933ca65a..9be01874e 100644 --- a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Scripts/Post-Deploy/Scripts/RequestTypeData.sql +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Scripts/Post-Deploy/Scripts/RequestTypeData.sql @@ -1,6 +1,14 @@ -INSERT [dbo].[RequestType] ([Id], [RequestType]) VALUES (1, N'Email') -GO +IF NOT EXISTS(SELECT Id FROM [dbo].[RequestType] WHERE Id = 1) +BEGIN +INSERT [dbo].[RequestType] ([Id], [RequestType]) VALUES (1, N'Email') +END + +IF NOT EXISTS(SELECT Id FROM [dbo].[RequestType] WHERE Id = 2) +BEGIN INSERT [dbo].[RequestType] ([Id], [RequestType]) VALUES (2, N'SMS') -GO +END + +IF NOT EXISTS(SELECT Id FROM [dbo].[RequestType] WHERE Id = 3) +BEGIN INSERT [dbo].[RequestType] ([Id], [RequestType]) VALUES (3, N'SingleEmail') -GO \ No newline at end of file +END \ No newline at end of file From c439704b18780106ca0d198c397b48969839c83b Mon Sep 17 00:00:00 2001 From: Arunima George Date: Tue, 24 Feb 2026 16:02:00 +0000 Subject: [PATCH 11/16] Merge latest from RC to Messaging service --- .../LearningHub.Nhs.AdminUI.csproj | 2 +- .../LearningHub.Nhs.WebUI.AutomatedUiTests.csproj | 2 +- LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj | 2 +- .../LearningHub.Nhs.MessageQueueing.csproj | 2 +- .../LearningHub.Nhs.MessagingService.csproj | 2 +- .../LearningHub.Nhs.OpenApi.Models.csproj | 2 +- .../LearningHub.Nhs.OpenApi.Repositories.Interface.csproj | 2 +- .../LearningHub.Nhs.OpenApi.Repositories.csproj | 2 +- .../LearningHub.Nhs.OpenApi.Services.Interface.csproj | 2 +- .../LearningHub.Nhs.OpenApi.Services.csproj | 2 +- .../Services/Messaging/GovMessageService.cs | 4 +--- .../LearningHub.Nhs.OpenApi.Tests.csproj | 2 +- .../Services/Services/CatalogueServiceTests.cs | 8 ++++++-- .../LearningHub.NHS.OpenAPI.csproj | 2 +- .../LearningHub.Nhs.ReportApi.Services.Interface.csproj | 2 +- .../LearningHub.Nhs.ReportApi.Services.UnitTests.csproj | 2 +- .../LearningHub.Nhs.ReportApi.Services.csproj | 2 +- .../LearningHub.Nhs.ReportApi.Shared.csproj | 2 +- .../LearningHub.Nhs.ReportApi.csproj | 2 +- WebAPI/LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj | 2 +- .../LearningHub.Nhs.Api.Shared.csproj | 2 +- .../LearningHub.Nhs.Api.UnitTests.csproj | 2 +- .../LearningHub.Nhs.Repository.Interface.csproj | 2 +- .../LearningHub.Nhs.Repository.csproj | 2 +- .../LearningHub.Nhs.Services.Interface.csproj | 2 +- .../LearningHub.Nhs.Services.UnitTests.csproj | 2 +- .../LearningHub.Nhs.Services.csproj | 2 +- .../LearningHub.Nhs.Migration.ConsoleApp.csproj | 2 +- .../LearningHub.Nhs.Migration.Interface.csproj | 2 +- .../LearningHub.Nhs.Migration.Models.csproj | 2 +- .../LearningHub.Nhs.Migration.Staging.Repository.csproj | 2 +- .../LearningHub.Nhs.Migration.UnitTests.csproj | 2 +- .../LearningHub.Nhs.Migration.csproj | 2 +- 33 files changed, 38 insertions(+), 36 deletions(-) diff --git a/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj b/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj index a42f95f98..a8f070053 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj +++ b/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj @@ -89,7 +89,7 @@ - + diff --git a/LearningHub.Nhs.WebUI.AutomatedUiTests/LearningHub.Nhs.WebUI.AutomatedUiTests.csproj b/LearningHub.Nhs.WebUI.AutomatedUiTests/LearningHub.Nhs.WebUI.AutomatedUiTests.csproj index 4c85e0949..23b92859c 100644 --- a/LearningHub.Nhs.WebUI.AutomatedUiTests/LearningHub.Nhs.WebUI.AutomatedUiTests.csproj +++ b/LearningHub.Nhs.WebUI.AutomatedUiTests/LearningHub.Nhs.WebUI.AutomatedUiTests.csproj @@ -13,7 +13,7 @@ - + diff --git a/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj b/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj index c8016ba86..f0521282a 100644 --- a/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj +++ b/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj @@ -112,7 +112,7 @@ - + diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing/LearningHub.Nhs.MessageQueueing.csproj b/MessageQueueing/LearningHub.Nhs.MessageQueueing/LearningHub.Nhs.MessageQueueing.csproj index 65f77786e..2b17c70d3 100644 --- a/MessageQueueing/LearningHub.Nhs.MessageQueueing/LearningHub.Nhs.MessageQueueing.csproj +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing/LearningHub.Nhs.MessageQueueing.csproj @@ -7,7 +7,7 @@ - + diff --git a/MessagingService/LearningHub.Nhs.MessagingService/LearningHub.Nhs.MessagingService.csproj b/MessagingService/LearningHub.Nhs.MessagingService/LearningHub.Nhs.MessagingService.csproj index 356759ba9..b8d67123b 100644 --- a/MessagingService/LearningHub.Nhs.MessagingService/LearningHub.Nhs.MessagingService.csproj +++ b/MessagingService/LearningHub.Nhs.MessagingService/LearningHub.Nhs.MessagingService.csproj @@ -8,7 +8,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Models/LearningHub.Nhs.OpenApi.Models.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Models/LearningHub.Nhs.OpenApi.Models.csproj index 16df89013..ae9a622e6 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Models/LearningHub.Nhs.OpenApi.Models.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Models/LearningHub.Nhs.OpenApi.Models.csproj @@ -17,7 +17,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/LearningHub.Nhs.OpenApi.Repositories.Interface.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/LearningHub.Nhs.OpenApi.Repositories.Interface.csproj index cbac27a64..acfceeb83 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/LearningHub.Nhs.OpenApi.Repositories.Interface.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/LearningHub.Nhs.OpenApi.Repositories.Interface.csproj @@ -17,7 +17,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/LearningHub.Nhs.OpenApi.Repositories.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/LearningHub.Nhs.OpenApi.Repositories.csproj index 6a727dc60..33302f623 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/LearningHub.Nhs.OpenApi.Repositories.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/LearningHub.Nhs.OpenApi.Repositories.csproj @@ -24,7 +24,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/LearningHub.Nhs.OpenApi.Services.Interface.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/LearningHub.Nhs.OpenApi.Services.Interface.csproj index 175ac7fb3..802661079 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/LearningHub.Nhs.OpenApi.Services.Interface.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/LearningHub.Nhs.OpenApi.Services.Interface.csproj @@ -17,7 +17,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj index f1e6f43be..87ce9883d 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj @@ -33,7 +33,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/Messaging/GovMessageService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/Messaging/GovMessageService.cs index 0428df905..558b9bc4c 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/Messaging/GovMessageService.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/Messaging/GovMessageService.cs @@ -28,16 +28,14 @@ public class GovMessageService : BaseService, IGovMessageService /// /// Initializes a new instance of the class. /// - /// The findwiseHttpClient. /// The logger. /// The message repository. /// The message Service. public GovMessageService( - IFindwiseClient findwiseClient, ILogger logger, IMessageQueueRepository messageQueueRepository, IGovNotifyService messageService) - : base(findwiseClient, logger) + : base(logger) { this.messageQueueRepository = messageQueueRepository; this.messageService = messageService; diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Tests/LearningHub.Nhs.OpenApi.Tests.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Tests/LearningHub.Nhs.OpenApi.Tests.csproj index 93461ce2b..27ab96576 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Tests/LearningHub.Nhs.OpenApi.Tests.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Tests/LearningHub.Nhs.OpenApi.Tests.csproj @@ -11,7 +11,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Tests/Services/Services/CatalogueServiceTests.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Tests/Services/Services/CatalogueServiceTests.cs index 66a6293ae..3c7e6f341 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Tests/Services/Services/CatalogueServiceTests.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Tests/Services/Services/CatalogueServiceTests.cs @@ -53,6 +53,7 @@ public class CatalogueServiceTests public CatalogueServiceTests() { this.catalogueRepository = new Mock(); + this.categoryService = new Mock(); this.mapper = new Mock(); this.catalogueNodeVersionRepository = new Mock(); this.catalogueAccessRequestRepository = new Mock(); @@ -74,8 +75,11 @@ public CatalogueServiceTests() this.timezoneOffsetManager = new Mock(); this.govMessageSevice = new Mock(); this.emailTemplateService = new Mock(); - this.categoryService = new Mock(); - this.catalogueService = new CatalogueService(this.catalogueRepository.Object, this.categoryService.Object, this.nodeRepository.Object, this.userUserGroupRepository.Object, this.mapper.Object, this.findwiseConfig.Object, this.learningHubConfig.Object, this.catalogueNodeVersionRepository.Object, this.nodeResourceRepository.Object, this.resourceVersionRepository.Object, this.roleUserGroupRepository.Object, this.providerService.Object, this.catalogueAccessRequestRepository.Object, this.userRepository.Object, this.userProfileRepository.Object, this.emailSenderService.Object, this.bookmarkRepository.Object, this.nodeActivityRepository.Object, this.findwiseApiFacade.Object, this.notificationSenderService.Object, this.timezoneOffsetManager.Object,, this.govMessageSevice.Object, this.emailTemplateService.Object); + this.catalogueService = new CatalogueService(this.catalogueRepository.Object, + this.nodeRepository.Object, this.userUserGroupRepository.Object, + this.mapper.Object, this.findwiseConfig.Object, this.learningHubConfig.Object, + this.catalogueNodeVersionRepository.Object, this.nodeResourceRepository.Object, this.resourceVersionRepository.Object, + this.roleUserGroupRepository.Object, this.providerService.Object, this.catalogueAccessRequestRepository.Object, this.userRepository.Object, this.userProfileRepository.Object, this.emailSenderService.Object, this.bookmarkRepository.Object, this.nodeActivityRepository.Object, this.findwiseApiFacade.Object, this.notificationSenderService.Object, this.timezoneOffsetManager.Object, this.categoryService.Object, this.govMessageSevice.Object, this.emailTemplateService.Object); } private static IEnumerable CatalogueNodeVersionList => new List() diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj b/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj index 57f75315b..7d5ab0178 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj @@ -19,7 +19,7 @@ - + diff --git a/ReportAPI/LearningHub.Nhs.ReportApi.Services.Interface/LearningHub.Nhs.ReportApi.Services.Interface.csproj b/ReportAPI/LearningHub.Nhs.ReportApi.Services.Interface/LearningHub.Nhs.ReportApi.Services.Interface.csproj index 2a259d6b2..79f6af7f9 100644 --- a/ReportAPI/LearningHub.Nhs.ReportApi.Services.Interface/LearningHub.Nhs.ReportApi.Services.Interface.csproj +++ b/ReportAPI/LearningHub.Nhs.ReportApi.Services.Interface/LearningHub.Nhs.ReportApi.Services.Interface.csproj @@ -16,7 +16,7 @@ - + diff --git a/ReportAPI/LearningHub.Nhs.ReportApi.Services.UnitTests/LearningHub.Nhs.ReportApi.Services.UnitTests.csproj b/ReportAPI/LearningHub.Nhs.ReportApi.Services.UnitTests/LearningHub.Nhs.ReportApi.Services.UnitTests.csproj index aebb8bb75..c8ca7a2ae 100644 --- a/ReportAPI/LearningHub.Nhs.ReportApi.Services.UnitTests/LearningHub.Nhs.ReportApi.Services.UnitTests.csproj +++ b/ReportAPI/LearningHub.Nhs.ReportApi.Services.UnitTests/LearningHub.Nhs.ReportApi.Services.UnitTests.csproj @@ -18,7 +18,7 @@ - + diff --git a/ReportAPI/LearningHub.Nhs.ReportApi.Services/LearningHub.Nhs.ReportApi.Services.csproj b/ReportAPI/LearningHub.Nhs.ReportApi.Services/LearningHub.Nhs.ReportApi.Services.csproj index acfb75739..89bca5ef2 100644 --- a/ReportAPI/LearningHub.Nhs.ReportApi.Services/LearningHub.Nhs.ReportApi.Services.csproj +++ b/ReportAPI/LearningHub.Nhs.ReportApi.Services/LearningHub.Nhs.ReportApi.Services.csproj @@ -19,7 +19,7 @@ - + diff --git a/ReportAPI/LearningHub.Nhs.ReportApi.Shared/LearningHub.Nhs.ReportApi.Shared.csproj b/ReportAPI/LearningHub.Nhs.ReportApi.Shared/LearningHub.Nhs.ReportApi.Shared.csproj index 9d86c24a0..ae1444ed9 100644 --- a/ReportAPI/LearningHub.Nhs.ReportApi.Shared/LearningHub.Nhs.ReportApi.Shared.csproj +++ b/ReportAPI/LearningHub.Nhs.ReportApi.Shared/LearningHub.Nhs.ReportApi.Shared.csproj @@ -17,7 +17,7 @@ - + diff --git a/ReportAPI/LearningHub.Nhs.ReportApi/LearningHub.Nhs.ReportApi.csproj b/ReportAPI/LearningHub.Nhs.ReportApi/LearningHub.Nhs.ReportApi.csproj index f31ff35e5..c19afef98 100644 --- a/ReportAPI/LearningHub.Nhs.ReportApi/LearningHub.Nhs.ReportApi.csproj +++ b/ReportAPI/LearningHub.Nhs.ReportApi/LearningHub.Nhs.ReportApi.csproj @@ -20,7 +20,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj b/WebAPI/LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj index 3a7660599..0462105ff 100644 --- a/WebAPI/LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj +++ b/WebAPI/LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj @@ -29,7 +29,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Api.Shared/LearningHub.Nhs.Api.Shared.csproj b/WebAPI/LearningHub.Nhs.Api.Shared/LearningHub.Nhs.Api.Shared.csproj index e1b7896b8..8d695c492 100644 --- a/WebAPI/LearningHub.Nhs.Api.Shared/LearningHub.Nhs.Api.Shared.csproj +++ b/WebAPI/LearningHub.Nhs.Api.Shared/LearningHub.Nhs.Api.Shared.csproj @@ -9,7 +9,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/WebAPI/LearningHub.Nhs.Api.UnitTests/LearningHub.Nhs.Api.UnitTests.csproj b/WebAPI/LearningHub.Nhs.Api.UnitTests/LearningHub.Nhs.Api.UnitTests.csproj index 4acbd2e13..100e6600d 100644 --- a/WebAPI/LearningHub.Nhs.Api.UnitTests/LearningHub.Nhs.Api.UnitTests.csproj +++ b/WebAPI/LearningHub.Nhs.Api.UnitTests/LearningHub.Nhs.Api.UnitTests.csproj @@ -11,7 +11,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Repository.Interface/LearningHub.Nhs.Repository.Interface.csproj b/WebAPI/LearningHub.Nhs.Repository.Interface/LearningHub.Nhs.Repository.Interface.csproj index 5d12c4600..8273e219f 100644 --- a/WebAPI/LearningHub.Nhs.Repository.Interface/LearningHub.Nhs.Repository.Interface.csproj +++ b/WebAPI/LearningHub.Nhs.Repository.Interface/LearningHub.Nhs.Repository.Interface.csproj @@ -10,7 +10,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Repository/LearningHub.Nhs.Repository.csproj b/WebAPI/LearningHub.Nhs.Repository/LearningHub.Nhs.Repository.csproj index b7cca29dc..a2628d76c 100644 --- a/WebAPI/LearningHub.Nhs.Repository/LearningHub.Nhs.Repository.csproj +++ b/WebAPI/LearningHub.Nhs.Repository/LearningHub.Nhs.Repository.csproj @@ -9,7 +9,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Services.Interface/LearningHub.Nhs.Services.Interface.csproj b/WebAPI/LearningHub.Nhs.Services.Interface/LearningHub.Nhs.Services.Interface.csproj index 6ee630341..73e99b72e 100644 --- a/WebAPI/LearningHub.Nhs.Services.Interface/LearningHub.Nhs.Services.Interface.csproj +++ b/WebAPI/LearningHub.Nhs.Services.Interface/LearningHub.Nhs.Services.Interface.csproj @@ -16,7 +16,7 @@ - + all diff --git a/WebAPI/LearningHub.Nhs.Services.UnitTests/LearningHub.Nhs.Services.UnitTests.csproj b/WebAPI/LearningHub.Nhs.Services.UnitTests/LearningHub.Nhs.Services.UnitTests.csproj index dbb1f6a30..6b02d693a 100644 --- a/WebAPI/LearningHub.Nhs.Services.UnitTests/LearningHub.Nhs.Services.UnitTests.csproj +++ b/WebAPI/LearningHub.Nhs.Services.UnitTests/LearningHub.Nhs.Services.UnitTests.csproj @@ -13,7 +13,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Services/LearningHub.Nhs.Services.csproj b/WebAPI/LearningHub.Nhs.Services/LearningHub.Nhs.Services.csproj index 98cec165a..d27db0e89 100644 --- a/WebAPI/LearningHub.Nhs.Services/LearningHub.Nhs.Services.csproj +++ b/WebAPI/LearningHub.Nhs.Services/LearningHub.Nhs.Services.csproj @@ -13,7 +13,7 @@ - + diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.ConsoleApp/LearningHub.Nhs.Migration.ConsoleApp.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.ConsoleApp/LearningHub.Nhs.Migration.ConsoleApp.csproj index 3a2cb8961..1a8367ea1 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.ConsoleApp/LearningHub.Nhs.Migration.ConsoleApp.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.ConsoleApp/LearningHub.Nhs.Migration.ConsoleApp.csproj @@ -25,7 +25,7 @@ - + all diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Interface/LearningHub.Nhs.Migration.Interface.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Interface/LearningHub.Nhs.Migration.Interface.csproj index b275eae94..56c3518c1 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Interface/LearningHub.Nhs.Migration.Interface.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Interface/LearningHub.Nhs.Migration.Interface.csproj @@ -9,7 +9,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Models/LearningHub.Nhs.Migration.Models.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Models/LearningHub.Nhs.Migration.Models.csproj index a18eb4196..e4a707d63 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Models/LearningHub.Nhs.Migration.Models.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Models/LearningHub.Nhs.Migration.Models.csproj @@ -10,7 +10,7 @@ - + all diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Staging.Repository/LearningHub.Nhs.Migration.Staging.Repository.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Staging.Repository/LearningHub.Nhs.Migration.Staging.Repository.csproj index bb23ca661..a6d13b605 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Staging.Repository/LearningHub.Nhs.Migration.Staging.Repository.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Staging.Repository/LearningHub.Nhs.Migration.Staging.Repository.csproj @@ -9,7 +9,7 @@ - + diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.UnitTests/LearningHub.Nhs.Migration.UnitTests.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.UnitTests/LearningHub.Nhs.Migration.UnitTests.csproj index 82a9b4aa6..2e25b373f 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.UnitTests/LearningHub.Nhs.Migration.UnitTests.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.UnitTests/LearningHub.Nhs.Migration.UnitTests.csproj @@ -10,7 +10,7 @@ - + diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration/LearningHub.Nhs.Migration.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration/LearningHub.Nhs.Migration.csproj index de745363e..e21f1b8e1 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration/LearningHub.Nhs.Migration.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration/LearningHub.Nhs.Migration.csproj @@ -12,7 +12,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive From 4bee6a8e2f18e495be860852af0d5a35a06be013 Mon Sep 17 00:00:00 2001 From: Arunima George Date: Fri, 20 Mar 2026 14:55:05 +0000 Subject: [PATCH 12/16] TD-6874: Implement GovNotify History in LH Admin UI --- .../GovNotifyDashboardController.cs | 120 ++++++++++++++++ .../Interfaces/IGovNotifyDashboardService.cs | 27 ++++ .../LearningHub.Nhs.AdminUI.csproj | 2 +- .../ServiceCollectionExtension.cs | 1 + .../Services/GovNotifyDashboardService.cs | 130 ++++++++++++++++++ .../Views/GovNotifyDashboard/Details.cshtml | 80 +++++++++++ .../Views/GovNotifyDashboard/Index.cshtml | 67 +++++++++ .../Views/Shared/_NavPartial.cshtml | 1 + .../Views/Shared/_NavSection.cshtml | 2 + ...rningHub.Nhs.WebUI.AutomatedUiTests.csproj | 2 +- .../LearningHub.Nhs.WebUI.csproj | 2 +- ...ngHub.Nhs.MessageQueueing.Database.sqlproj | 2 + .../GetAllMessageRequests.sql | 129 +++++++++++++++++ .../GetMessageRequestById.sql | 24 ++++ .../EntityFramework/MessageQueueDbContext.cs | 5 + .../LearningHub.Nhs.MessageQueueing.csproj | 2 +- .../Repositories/IMessageQueueRepository.cs | 19 +++ .../Repositories/MessageQueueRepository.cs | 46 ++++++- .../LearningHub.Nhs.MessagingService.csproj | 2 +- .../LearningHub.Nhs.OpenApi.Models.csproj | 2 +- ....Nhs.OpenApi.Repositories.Interface.csproj | 2 +- ...earningHub.Nhs.OpenApi.Repositories.csproj | 2 +- ...gHub.Nhs.OpenApi.Services.Interface.csproj | 2 +- .../Services/Messaging/IGovMessageService.cs | 18 ++- .../LearningHub.Nhs.OpenApi.Services.csproj | 2 +- .../Services/Messaging/GovMessageService.cs | 34 ++++- .../LearningHub.Nhs.OpenApi.Tests.csproj | 2 +- .../GovNotifyMessagingController.cs | 36 ++++- .../LearningHub.NHS.OpenAPI.csproj | 2 +- ...ub.Nhs.ReportApi.Services.Interface.csproj | 2 +- ...ub.Nhs.ReportApi.Services.UnitTests.csproj | 2 +- .../LearningHub.Nhs.ReportApi.Services.csproj | 2 +- .../LearningHub.Nhs.ReportApi.Shared.csproj | 2 +- .../LearningHub.Nhs.ReportApi.csproj | 2 +- .../LearningHub.Nhs.Api.csproj | 2 +- .../LearningHub.Nhs.Api.Shared.csproj | 2 +- .../LearningHub.Nhs.Api.UnitTests.csproj | 2 +- ...earningHub.Nhs.Repository.Interface.csproj | 2 +- .../LearningHub.Nhs.Repository.csproj | 2 +- .../LearningHub.Nhs.Services.Interface.csproj | 2 +- .../LearningHub.Nhs.Services.UnitTests.csproj | 2 +- .../LearningHub.Nhs.Services.csproj | 2 +- ...earningHub.Nhs.Migration.ConsoleApp.csproj | 2 +- ...LearningHub.Nhs.Migration.Interface.csproj | 2 +- .../LearningHub.Nhs.Migration.Models.csproj | 2 +- ...ub.Nhs.Migration.Staging.Repository.csproj | 2 +- ...LearningHub.Nhs.Migration.UnitTests.csproj | 2 +- .../LearningHub.Nhs.Migration.csproj | 2 +- 48 files changed, 757 insertions(+), 46 deletions(-) create mode 100644 AdminUI/LearningHub.Nhs.AdminUI/Controllers/GovNotifyDashboardController.cs create mode 100644 AdminUI/LearningHub.Nhs.AdminUI/Interfaces/IGovNotifyDashboardService.cs create mode 100644 AdminUI/LearningHub.Nhs.AdminUI/Services/GovNotifyDashboardService.cs create mode 100644 AdminUI/LearningHub.Nhs.AdminUI/Views/GovNotifyDashboard/Details.cshtml create mode 100644 AdminUI/LearningHub.Nhs.AdminUI/Views/GovNotifyDashboard/Index.cshtml create mode 100644 MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/GetAllMessageRequests.sql create mode 100644 MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/GetMessageRequestById.sql diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Controllers/GovNotifyDashboardController.cs b/AdminUI/LearningHub.Nhs.AdminUI/Controllers/GovNotifyDashboardController.cs new file mode 100644 index 000000000..d6826bcd2 --- /dev/null +++ b/AdminUI/LearningHub.Nhs.AdminUI/Controllers/GovNotifyDashboardController.cs @@ -0,0 +1,120 @@ +using LearningHub.Nhs.AdminUI.Configuration; +using LearningHub.Nhs.AdminUI.Extensions; +using LearningHub.Nhs.AdminUI.Interfaces; +using LearningHub.Nhs.Models.Paging; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Options; +using Newtonsoft.Json; +using System.Collections.Generic; +using System.Linq; +using System; +using System.Threading.Tasks; +using LearningHub.Nhs.Models.GovNotifyMessaging; + +namespace LearningHub.Nhs.AdminUI.Controllers +{ + /// + /// Defines the . + /// + public class GovNotifyDashboardController : BaseController + { + /// + /// Defines the websettings. + /// + private readonly IOptions websettings; + + /// + /// Defines the govNotifyDashboardService. + /// + private IGovNotifyDashboardService govNotifyDashboardService; + + /// + /// Initializes a new instance of the class. + /// + /// The hostingEnvironment. + /// The govNotifyDashboardService. + /// The websettings. + public GovNotifyDashboardController(IWebHostEnvironment hostingEnvironment, + IGovNotifyDashboardService govNotifyDashboardService, + IOptions websettings) + : base(hostingEnvironment) + { + this.websettings = websettings; + this.govNotifyDashboardService = govNotifyDashboardService; + } + + /// + /// Initial call to get paginated result. + /// + /// The . + public async Task Index() + { + return await this.GetMessageRequests( + new PagingRequestModel + { + Page = 1, + PageSize = this.websettings.Value.DefaultPageSize, + SortColumn = "CreatedAt", + SortDirection = "D", + }); + } + + /// + /// Get paginated result based on the filters. + /// + /// + /// The . + [HttpPost] + public async Task Index(string pagingRequestModel) + { + var requestModel = JsonConvert.DeserializeObject(pagingRequestModel); + return await this.GetMessageRequests(requestModel); + } + + /// + /// Get message request details by id. + /// + /// + /// The . + [HttpGet] + public async Task Details(int id) + { + var notification = await this.govNotifyDashboardService.GetMessageRequestById(id); + return this.View(notification); + } + + private async Task GetMessageRequests(PagingRequestModel requestModel) + { + requestModel.Sanitize(); + requestModel.PageSize = this.websettings.Value.DefaultPageSize; + + var model = new TablePagingViewModel + { + Results = await this.govNotifyDashboardService.GetPagedAsync(requestModel), + SortColumn = requestModel.SortColumn, + SortDirection = requestModel.SortDirection, + Filter = requestModel.Filter, + }; + + model.Paging = new PagingViewModel + { + CurrentPage = requestModel.Page, + HasItems = model.Results.Items.Any(), + PageSize = this.websettings.Value.DefaultPageSize, + TotalItems = model.Results.TotalItemCount, + }; + + model.ListPageHeader = new ListPageHeaderViewModel + { + TotalItemCount = model.Results.TotalItemCount, + DisplayedCount = model.Results.Items.Count(), + DefaultPageSize = this.websettings.Value.DefaultPageSize, + FilterCount = model.Filter != null ? model.Filter.Count() : 0, + CreateRequired = false, + }; + + return this.View(model); + } + } +} diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Interfaces/IGovNotifyDashboardService.cs b/AdminUI/LearningHub.Nhs.AdminUI/Interfaces/IGovNotifyDashboardService.cs new file mode 100644 index 000000000..0a5368a13 --- /dev/null +++ b/AdminUI/LearningHub.Nhs.AdminUI/Interfaces/IGovNotifyDashboardService.cs @@ -0,0 +1,27 @@ +namespace LearningHub.Nhs.AdminUI.Interfaces +{ + using LearningHub.Nhs.Models.Common; + using LearningHub.Nhs.Models.GovNotifyMessaging; + using LearningHub.Nhs.Models.Paging; + using System.Threading.Tasks; + + /// + /// Defines the . + /// + public interface IGovNotifyDashboardService + { + /// + /// The GetPagedAsync. + /// + /// The pagingRequestModel. + /// The . + Task> GetPagedAsync(PagingRequestModel pagingRequestModel); + + /// + /// Get Message Request By Id. + /// + /// id. + /// The . + Task GetMessageRequestById(int id); + } +} diff --git a/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj b/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj index a8f070053..a868c30dd 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj +++ b/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj @@ -89,7 +89,7 @@ - + diff --git a/AdminUI/LearningHub.Nhs.AdminUI/ServiceCollectionExtension.cs b/AdminUI/LearningHub.Nhs.AdminUI/ServiceCollectionExtension.cs index 9137a55e7..f6e098c3e 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/ServiceCollectionExtension.cs +++ b/AdminUI/LearningHub.Nhs.AdminUI/ServiceCollectionExtension.cs @@ -107,6 +107,7 @@ public static void ConfigureServices(this IServiceCollection services, IConfigur services.AddTransient(); services.AddScoped(); services.AddScoped(); + services.AddScoped(); // Configure Azure Search services.Configure(configuration.GetSection("AzureSearch")); diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Services/GovNotifyDashboardService.cs b/AdminUI/LearningHub.Nhs.AdminUI/Services/GovNotifyDashboardService.cs new file mode 100644 index 000000000..e82a1c468 --- /dev/null +++ b/AdminUI/LearningHub.Nhs.AdminUI/Services/GovNotifyDashboardService.cs @@ -0,0 +1,130 @@ +using LearningHub.Nhs.AdminUI.Interfaces; +using LearningHub.Nhs.Models.Common; +using LearningHub.Nhs.Models.Paging; +using Newtonsoft.Json; +using System.Threading.Tasks; +using System; +using LearningHub.Nhs.Models.GovNotifyMessaging; +using Newtonsoft.Json.Converters; +using System.Collections.Generic; + +namespace LearningHub.Nhs.AdminUI.Services +{ + /// + /// Defines the . + /// + public class GovNotifyDashboardService: BaseService, IGovNotifyDashboardService + { + /// + /// Initializes a new instance of the class. + /// + /// + /// + public GovNotifyDashboardService(ILearningHubHttpClient learningHubHttpClient, IOpenApiHttpClient openApiHttpClient) + :base(learningHubHttpClient, openApiHttpClient) + { + } + + /// + /// The GetPagedAsync. + /// + /// The pagingRequestModel. + /// The . + public async Task> GetPagedAsync(PagingRequestModel pagingRequestModel) + { + try + { + PagedResultSet viewmodel = null; + var sortDirection = " "; + + if (string.IsNullOrEmpty(pagingRequestModel.SortColumn)) + { + pagingRequestModel.SortColumn = " "; + } + + if (string.IsNullOrEmpty(pagingRequestModel.SortDirection)) + { + pagingRequestModel.SortDirection = " "; + } + else + { + sortDirection = pagingRequestModel.SortDirection == "A" ? "ASC" : + pagingRequestModel.SortDirection == "D" ? "DESC" : "ASC"; + } + + var settings = new JsonSerializerSettings + { + Converters = new List + { + new StringEnumConverter() + } + }; + + var filter = JsonConvert.SerializeObject(pagingRequestModel.Filter, settings); + var client = await this.OpenApiHttpClient.GetClientAsync(); + + var request = $"GovNotifyMessage/GetMessageRequests" + + $"/{pagingRequestModel.Page}" + + $"/{pagingRequestModel.PageSize}" + + $"/{pagingRequestModel.SortColumn}" + + $"/{sortDirection}" + +$"/{Uri.EscapeDataString(filter)}"; + + var response = await client.GetAsync(request).ConfigureAwait(false); + + if (response.IsSuccessStatusCode) + { + var result = response.Content.ReadAsStringAsync().Result; + viewmodel = JsonConvert.DeserializeObject>(result); + } + else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized + || + response.StatusCode == System.Net.HttpStatusCode.Forbidden) + { + throw new Exception("AccessDenied"); + } + + return viewmodel; + } + catch (Exception ex) + { + return null; + } + } + + /// + /// Get message request details by id. + /// + /// id. + /// The . + public async Task GetMessageRequestById(int id) + { + try + { + MessageRequestViewModel viewmodel = null; + var client = await this.OpenApiHttpClient.GetClientAsync(); + + var request = $"GovNotifyMessage/GetMessageRequestById/{id}"; + var response = await client.GetAsync(request).ConfigureAwait(false); + + if (response.IsSuccessStatusCode) + { + var result = response.Content.ReadAsStringAsync().Result; + viewmodel = JsonConvert.DeserializeObject(result); + } + else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized + || + response.StatusCode == System.Net.HttpStatusCode.Forbidden) + { + throw new Exception("AccessDenied"); + } + + return viewmodel; + } + catch (Exception ex) + { + return null; + } + } + } +} diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Views/GovNotifyDashboard/Details.cshtml b/AdminUI/LearningHub.Nhs.AdminUI/Views/GovNotifyDashboard/Details.cshtml new file mode 100644 index 000000000..fcffc0eae --- /dev/null +++ b/AdminUI/LearningHub.Nhs.AdminUI/Views/GovNotifyDashboard/Details.cshtml @@ -0,0 +1,80 @@ +@model LearningHub.Nhs.Models.GovNotifyMessaging.MessageRequestViewModel +@using LearningHub.Nhs.AdminUI.Services + +@{ + ViewData["Title"] = "Details"; +} +@section SideMenu { + @{ + await Html.RenderPartialAsync("_NavSection"); + } +} + +
+ +
+
+
ID @Model.Id
+
+
+ Recipient +
+
+ @Html.DisplayFor(model => model.Recipient) +
+
+ Request type +
+
+ @Html.DisplayFor(model => model.RequestType) +
+
+ Request status +
+
+ @Html.DisplayFor(model => model.RequestStatus) +
+
+ Retry count +
+
+ @Html.DisplayFor(model => model.RetryCount) +
+
+ Created date +
+
+ @Html.DisplayFor(model => model.CreatedAt) +
+
+ Deliver after date +
+
+ @Html.DisplayFor(model => model.DeliverAfter) +
+
+ Sent Date +
+
+ @Html.DisplayFor(model => model.SentAt) +
+
+ Last attempt date +
+
+ @Html.DisplayFor(model => model.LastAttemptAt) +
+
+ Error message +
+
+ @Html.Raw(OutputSanitizer.SanitizeOutputHtml(Model.ErrorMessage)) +
+
+
+
+ +
+ diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Views/GovNotifyDashboard/Index.cshtml b/AdminUI/LearningHub.Nhs.AdminUI/Views/GovNotifyDashboard/Index.cshtml new file mode 100644 index 000000000..a1a83b1b4 --- /dev/null +++ b/AdminUI/LearningHub.Nhs.AdminUI/Views/GovNotifyDashboard/Index.cshtml @@ -0,0 +1,67 @@ +@using LearningHub.Nhs.Models.GovNotifyMessaging +@using LearningHub.Nhs.Models.Enums +@using LearningHub.Nhs.AdminUI.Controllers +@model LearningHub.Nhs.Models.Paging.TablePagingViewModel + +@{ + ViewData["Title"] = "GovNotify Dashboard"; + ViewData["CurrentPage"] = Model.Paging.CurrentPage; +} + +@section SideMenu { + @{ + await Html.RenderPartialAsync("_NavSection"); + } +} +@{ + await Html.RenderPartialAsync("_ListPageHeader", Model.ListPageHeader); +} + +
+ + + + + + + + + + + + + @if (Model.Paging.HasItems) + { + foreach (var request in Model.Results.Items) + { + + + + + + + + + } + } + +
IdRequestTypeRecipientRequestStatusRetryCountCreated Date
@request.Id@request.RequestType + @Html.ActionLink(request.Recipient, "Details", new { id = request.Id }) + @request.RequestStatus@request.RetryCount@request.CreatedAt.LocalDateTime.ToString("dd/MM/yyyy HH:mm:ss")
+
+@{ + await Html.RenderPartialAsync("_PagingControls", Model.Paging); +} + + +@section Scripts { + + +} \ No newline at end of file diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Views/Shared/_NavPartial.cshtml b/AdminUI/LearningHub.Nhs.AdminUI/Views/Shared/_NavPartial.cshtml index 6a6e66a26..4373eb821 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/Views/Shared/_NavPartial.cshtml +++ b/AdminUI/LearningHub.Nhs.AdminUI/Views/Shared/_NavPartial.cshtml @@ -13,6 +13,7 @@ switch (controller) { case "notifications": + case "govnotifydashboard": case "externalsystem": case "log": case "roadmap": diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Views/Shared/_NavSection.cshtml b/AdminUI/LearningHub.Nhs.AdminUI/Views/Shared/_NavSection.cshtml index 924c58475..3285d08db 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/Views/Shared/_NavSection.cshtml +++ b/AdminUI/LearningHub.Nhs.AdminUI/Views/Shared/_NavSection.cshtml @@ -5,6 +5,7 @@ switch (controller) { case "notifications": + case "govnotifydashboard": case "externalsystem": case "log": case "release": @@ -45,6 +46,7 @@
  • Release management
  • Cache management
  • Service updates and releases
  • +
  • GovNotify Dashboard
  • break; case "users": diff --git a/LearningHub.Nhs.WebUI.AutomatedUiTests/LearningHub.Nhs.WebUI.AutomatedUiTests.csproj b/LearningHub.Nhs.WebUI.AutomatedUiTests/LearningHub.Nhs.WebUI.AutomatedUiTests.csproj index 23b92859c..fe1c6b73b 100644 --- a/LearningHub.Nhs.WebUI.AutomatedUiTests/LearningHub.Nhs.WebUI.AutomatedUiTests.csproj +++ b/LearningHub.Nhs.WebUI.AutomatedUiTests/LearningHub.Nhs.WebUI.AutomatedUiTests.csproj @@ -13,7 +13,7 @@ - + diff --git a/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj b/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj index f0521282a..1da7ce929 100644 --- a/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj +++ b/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj @@ -112,7 +112,7 @@ - + diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/LearningHub.Nhs.MessageQueueing.Database.sqlproj b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/LearningHub.Nhs.MessageQueueing.Database.sqlproj index 36694de1f..502e072a3 100644 --- a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/LearningHub.Nhs.MessageQueueing.Database.sqlproj +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/LearningHub.Nhs.MessageQueueing.Database.sqlproj @@ -73,6 +73,8 @@ + + diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/GetAllMessageRequests.sql b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/GetAllMessageRequests.sql new file mode 100644 index 000000000..a6ce589dc --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/GetAllMessageRequests.sql @@ -0,0 +1,129 @@ +------------------------------------------------------------------------------- +-- Author Arunima George +-- Created 18-03-2026 +-- Purpose Get paginated message requests. +-- +-- Modification History +-- +-- 18-03-2026 Arunima George Initial Revision +------------------------------------------------------------------------------- + +CREATE PROCEDURE [dbo].[GetAllMessageRequests] + @offSet int, + @fetchRows int, + @SortColumn NVARCHAR(50) = 'CreatedAt', + @SortDirection NVARCHAR(4) = 'DESC', + @Filters NVARCHAR(MAX) = NULL, + @totalCount INT OUTPUT +AS +BEGIN +SET NOCOUNT ON; + +IF @SortColumn NOT IN ( +'Id','RequestType','Recipient','RequestStatus', +'RetryCount','CreatedAt' +) +SET @SortColumn = 'CreatedAt' + +IF @SortDirection NOT IN ('ASC','DESC') +SET @SortDirection = 'DESC' + +IF @Filters IS NULL OR @Filters = '' OR @Filters = 'null' +BEGIN + SET @Filters = '[]' +END + +DECLARE @WhereClause NVARCHAR(MAX) = '' + +------------------------------------------------ +-- Build WHERE clause from JSON filters +------------------------------------------------ + +SELECT @WhereClause = +STRING_AGG( + CASE + WHEN FilterType = 'Text' + THEN QUOTENAME(ColumnName) + ' LIKE ''%' + FilterValue + '%''' + + WHEN FilterType = 'Number' + THEN + CASE ColumnName + WHEN 'Id' THEN 'qr.Id' + WHEN 'RetryCount' THEN 'qr.RetryCount' + END + + ' = ' + FilterValue + + WHEN FilterType = 'Date' + THEN + CASE ColumnName + WHEN 'CreatedAt' THEN + 'qr.CreatedAt >= ''' + FilterValue + ''' AND qr.CreatedAt < DATEADD(DAY,1,''' + FilterValue + ''')' + END + + ELSE NULL + END +,' AND ') +FROM OPENJSON(@Filters) +WITH +( + ColumnName NVARCHAR(50) '$.Column', + FilterType NVARCHAR(50) '$.Type', + FilterValue NVARCHAR(200) '$.Value' +) + +------------------------------------------------ +-- Base Query +------------------------------------------------ + +DECLARE @SQL NVARCHAR(MAX) + +SET @SQL = ' +SELECT + qr.Id, + rt.RequestType, + qr.Recipient, + rs.RequestStatus, + qr.RetryCount, + qr.CreatedAt, + qr.DeliverAfter, + qr.SentAt, + qr.LastAttemptAt, + qr.ErrorMessage +FROM QueueRequests qr +JOIN RequestType rt ON qr.RequestTypeId = rt.Id +JOIN RequestStatus rs ON qr.Status = rs.Id +' + +IF @WhereClause IS NOT NULL AND LEN(@WhereClause) > 0 +BEGIN + SET @SQL = @SQL + ' WHERE ' + @WhereClause +END + + +------------------------------------------------ +-- Total Count +------------------------------------------------ + +DECLARE @CountSQL NVARCHAR(MAX) + +SET @CountSQL = 'SELECT @TotalCount = COUNT(*) FROM (' + @SQL + ') A' + +EXEC sp_executesql +@CountSQL, +N'@TotalCount INT OUTPUT', +@TotalCount OUTPUT + + +------------------------------------------------ +-- Pagination Query +------------------------------------------------ + +SET @SQL = @SQL + ' + ORDER BY ' + QUOTENAME(@SortColumn) + ' ' + @SortDirection + ' + OFFSET ' + CAST(@Offset AS NVARCHAR) + ' ROWS + FETCH NEXT ' + CAST(@fetchRows AS NVARCHAR) + ' ROWS ONLY' + +EXEC(@SQL) + +END +GO diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/GetMessageRequestById.sql b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/GetMessageRequestById.sql new file mode 100644 index 000000000..03ade3260 --- /dev/null +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing.Database/Stored Procedures/GetMessageRequestById.sql @@ -0,0 +1,24 @@ +------------------------------------------------------------------------------- +-- Author Arunima George +-- Created 18-03-2026 +-- Purpose To get message request details by id. +-- +-- Modification History +-- +-- 18-03-2026 Arunima George Initial Revision +------------------------------------------------------------------------------- + +CREATE PROCEDURE [dbo].[GetMessageRequestById] +@id int +AS +BEGIN +SET NOCOUNT ON; + select qr.Id,rt.RequestType,Recipient,rs.RequestStatus,RetryCount,CreatedAt,DeliverAfter,SentAt,LastAttemptAt,ErrorMessage + from dbo.QueueRequests qr + left join RequestType as rt on rt.Id = qr.RequestTypeId + left join RequestStatus as rs on rs.Id = qr.Status + where qr.Id = @Id + + +END +GO diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing/EntityFramework/MessageQueueDbContext.cs b/MessageQueueing/LearningHub.Nhs.MessageQueueing/EntityFramework/MessageQueueDbContext.cs index f6c1d5870..d889ebf3f 100644 --- a/MessageQueueing/LearningHub.Nhs.MessageQueueing/EntityFramework/MessageQueueDbContext.cs +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing/EntityFramework/MessageQueueDbContext.cs @@ -35,5 +35,10 @@ public MessageQueueDbContextOptions Options /// Gets or sets the PendingMessageRequests. ///
    public virtual DbSet PendingMessageRequests { get; set; } + + /// + /// Gets or sets the MessageRequestViewModel. + /// + public virtual DbSet MessageRequestViewModel { get; set; } } } diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing/LearningHub.Nhs.MessageQueueing.csproj b/MessageQueueing/LearningHub.Nhs.MessageQueueing/LearningHub.Nhs.MessageQueueing.csproj index 2b17c70d3..a304ded70 100644 --- a/MessageQueueing/LearningHub.Nhs.MessageQueueing/LearningHub.Nhs.MessageQueueing.csproj +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing/LearningHub.Nhs.MessageQueueing.csproj @@ -7,7 +7,7 @@ - + diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/IMessageQueueRepository.cs b/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/IMessageQueueRepository.cs index 825b61972..2685e4009 100644 --- a/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/IMessageQueueRepository.cs +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/IMessageQueueRepository.cs @@ -2,6 +2,7 @@ { using System.Collections.Generic; using System.Threading.Tasks; + using LearningHub.Nhs.Models.Common; using LearningHub.Nhs.Models.Entities.GovNotifyMessaging; using LearningHub.Nhs.Models.GovNotifyMessaging; @@ -43,5 +44,23 @@ public interface IMessageQueueRepository /// The email request. /// The . Task SaveSingleEmailTransactions(SingleEmailRequest request); + + /// + /// The GetPaginatedMessageRequests. + /// + /// offSet count. + /// fetchRows count. + /// sort column. + /// sort direction. + /// filter. + /// The . + Task> GetPaginatedMessageRequests(int? offSet, int? fetchRows, string sortColumn, string sortDirection, string filter); + + /// + /// Get Message Request By Id. + /// + /// id. + /// The . + Task GetMessageRequestById(int id); } } diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/MessageQueueRepository.cs b/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/MessageQueueRepository.cs index 2089c41fa..071e6f364 100644 --- a/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/MessageQueueRepository.cs +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing/Repositories/MessageQueueRepository.cs @@ -3,9 +3,12 @@ using System; using System.Collections.Generic; using System.Data; + using System.Linq; using System.Threading.Tasks; + using AutoMapper; using LearningHub.Nhs.MessageQueueing.EntityFramework; using LearningHub.Nhs.MessageQueueing.Helpers; + using LearningHub.Nhs.Models.Common; using LearningHub.Nhs.Models.Entities.GovNotifyMessaging; using LearningHub.Nhs.Models.GovNotifyMessaging; using Microsoft.Data.SqlClient; @@ -17,14 +20,17 @@ public class MessageQueueRepository : IMessageQueueRepository { private readonly MessageQueueDbContext dbContext; + private readonly IMapper mapper; /// /// Initializes a new instance of the class. /// /// The context. - public MessageQueueRepository(MessageQueueDbContext dbContext) + /// mapper. + public MessageQueueRepository(MessageQueueDbContext dbContext, IMapper mapper) { this.dbContext = dbContext; + this.mapper = mapper; } /// @@ -88,5 +94,43 @@ public async Task SaveSingleEmailTransactions(SingleEmailRequest request) var param4 = new SqlParameter("@p4", SqlDbType.NVarChar) { Value = request.ErrorMessage == null ? DBNull.Value : request.ErrorMessage }; await this.dbContext.Database.ExecuteSqlRawAsync("dbo.SaveSingleEmailTransactions @p0, @p1, @p2, @p3, @p4", param0, param1, param2, param3, param4); } + + /// + /// The Get Paginated MessageRequests. + /// + /// offset count. + /// fetch rows. + /// sort column. + /// sort direction. + /// filter. + /// The . + public async Task> GetPaginatedMessageRequests(int? offSet, int? fetchRows, string sortColumn, string sortDirection, string filter) + { + var result = new PagedResultSet(); + var param0 = new SqlParameter("@offSet", SqlDbType.Int) { Value = offSet }; + var param1 = new SqlParameter("@fetchRows", SqlDbType.Int) { Value = fetchRows }; + var param2 = new SqlParameter("@sortColumn", SqlDbType.Text) { Value = sortColumn }; + var param3 = new SqlParameter("@sortDirection", SqlDbType.Text) { Value = sortDirection }; + var param4 = new SqlParameter("@filter", SqlDbType.Text) { Value = filter }; + var param5 = new SqlParameter("@totalCount", SqlDbType.Int) { Direction = ParameterDirection.Output }; + var requests = await this.dbContext.MessageRequestViewModel.FromSqlRaw("dbo.GetAllMessageRequests @offSet,@fetchRows,@sortColumn,@sortDirection,@filter,@totalCount output ", param0, param1, param2, param3, param4, param5) + .AsNoTracking().ToListAsync(); + result.TotalItemCount = (int)param5.Value; + result.Items = mapper.Map>(requests); + return result; + } + + /// + /// Get Message Request By Id. + /// + /// id. + /// The . + public async Task GetMessageRequestById(int id) + { + var param0 = new SqlParameter("@id", SqlDbType.Int) { Value = id }; + var result = await this.dbContext.MessageRequestViewModel.FromSqlRaw("dbo.GetMessageRequestById @id", param0).AsNoTracking().ToListAsync(); + MessageRequestViewModel messageRequestViewModel = result.AsEnumerable().FirstOrDefault(); + return messageRequestViewModel; + } } } diff --git a/MessagingService/LearningHub.Nhs.MessagingService/LearningHub.Nhs.MessagingService.csproj b/MessagingService/LearningHub.Nhs.MessagingService/LearningHub.Nhs.MessagingService.csproj index b8d67123b..c1bef3c93 100644 --- a/MessagingService/LearningHub.Nhs.MessagingService/LearningHub.Nhs.MessagingService.csproj +++ b/MessagingService/LearningHub.Nhs.MessagingService/LearningHub.Nhs.MessagingService.csproj @@ -8,7 +8,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Models/LearningHub.Nhs.OpenApi.Models.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Models/LearningHub.Nhs.OpenApi.Models.csproj index ae9a622e6..50dba8227 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Models/LearningHub.Nhs.OpenApi.Models.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Models/LearningHub.Nhs.OpenApi.Models.csproj @@ -17,7 +17,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/LearningHub.Nhs.OpenApi.Repositories.Interface.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/LearningHub.Nhs.OpenApi.Repositories.Interface.csproj index acfceeb83..e9ab9a72c 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/LearningHub.Nhs.OpenApi.Repositories.Interface.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/LearningHub.Nhs.OpenApi.Repositories.Interface.csproj @@ -17,7 +17,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/LearningHub.Nhs.OpenApi.Repositories.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/LearningHub.Nhs.OpenApi.Repositories.csproj index 33302f623..e1944021f 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/LearningHub.Nhs.OpenApi.Repositories.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/LearningHub.Nhs.OpenApi.Repositories.csproj @@ -24,7 +24,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/LearningHub.Nhs.OpenApi.Services.Interface.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/LearningHub.Nhs.OpenApi.Services.Interface.csproj index 802661079..509e9e928 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/LearningHub.Nhs.OpenApi.Services.Interface.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/LearningHub.Nhs.OpenApi.Services.Interface.csproj @@ -17,7 +17,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/Messaging/IGovMessageService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/Messaging/IGovMessageService.cs index 0de40c83e..4dd4a0969 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/Messaging/IGovMessageService.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/Messaging/IGovMessageService.cs @@ -1,12 +1,9 @@ namespace LearningHub.Nhs.OpenApi.Services.Interface.Services.Messaging { using System; - using System.Collections.Generic; using System.Threading.Tasks; + using LearningHub.Nhs.Models.Common; using LearningHub.Nhs.Models.GovNotifyMessaging; - using LearningHub.Nhs.Models.Messaging; - using LearningHub.Nhs.Models.Validation; - using Microsoft.AspNetCore.Mvc; /// /// The IGovMessageService interface. @@ -27,5 +24,18 @@ public interface IGovMessageService /// The QueueRequestList. /// The . Task QueueRequestsAsync(QueueMessageList request); + + /// + /// Get Message Requests. + /// + /// The . + Task> GetMessageRequests(int page, int pageSize, string sortColumn, string sortDirection, string filter); + + /// + /// Get Message request by Id + /// + /// + /// The . + Task GetMessageRequestById(int id); } } diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj index 87ce9883d..e3d2b217c 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj @@ -33,7 +33,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/Messaging/GovMessageService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/Messaging/GovMessageService.cs index 558b9bc4c..77328c256 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/Messaging/GovMessageService.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/Messaging/GovMessageService.cs @@ -1,19 +1,17 @@ namespace LearningHub.Nhs.OpenApi.Services.Services.Messaging { using System; - using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; + using AutoMapper; using LearningHub.Nhs.MessageQueueing.Repositories; using LearningHub.Nhs.MessagingService.Interfaces; + using LearningHub.Nhs.Models.Common; using LearningHub.Nhs.Models.Entities.GovNotifyMessaging; using LearningHub.Nhs.Models.Entities.Messaging; using LearningHub.Nhs.Models.Enums.GovNotifyMessaging; using LearningHub.Nhs.Models.GovNotifyMessaging; - using LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories.Messaging; - using LearningHub.Nhs.OpenApi.Services.Interface.HttpClients; using LearningHub.Nhs.OpenApi.Services.Interface.Services.Messaging; - using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Newtonsoft.Json; @@ -24,6 +22,7 @@ public class GovMessageService : BaseService, IGovMessageService { private readonly IMessageQueueRepository messageQueueRepository; private readonly IGovNotifyService messageService; + private readonly IMapper mapper; /// /// Initializes a new instance of the class. @@ -31,14 +30,17 @@ public class GovMessageService : BaseService, IGovMessageService /// The logger. /// The message repository. /// The message Service. + /// mapper. public GovMessageService( ILogger logger, IMessageQueueRepository messageQueueRepository, - IGovNotifyService messageService) + IGovNotifyService messageService, + IMapper mapper) : base(logger) { this.messageQueueRepository = messageQueueRepository; this.messageService = messageService; + this.mapper = mapper; } /// @@ -101,5 +103,27 @@ public async Task QueueRequestsAsync(QueueMessageList request) await this.messageQueueRepository.QueueMessagesAsync(requests); } + + /// + /// Get paginated Message Requests. + /// + /// The . + public async Task> GetMessageRequests(int page, int pageSize, string sortColumn, string sortDirection, string filter) + { + int? offset = (page - 1) * pageSize; + var result = await this.messageQueueRepository.GetPaginatedMessageRequests(offset, pageSize, sortColumn, sortDirection, filter); + return result; + } + + /// + /// Get message request details by Id. + /// + /// + /// The . + public async Task GetMessageRequestById(int id) + { + var result = await this.messageQueueRepository.GetMessageRequestById(id); + return result; + } } } diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Tests/LearningHub.Nhs.OpenApi.Tests.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Tests/LearningHub.Nhs.OpenApi.Tests.csproj index 27ab96576..6e8a17e14 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Tests/LearningHub.Nhs.OpenApi.Tests.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Tests/LearningHub.Nhs.OpenApi.Tests.csproj @@ -11,7 +11,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/GovNotifyMessagingController.cs b/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/GovNotifyMessagingController.cs index 37b41f1cc..e7600ff23 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/GovNotifyMessagingController.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/GovNotifyMessagingController.cs @@ -2,18 +2,14 @@ { using System; using System.Collections.Generic; - using System.Linq; using System.Threading.Tasks; using LearningHub.Nhs.MessageQueueing.Repositories; using LearningHub.Nhs.MessagingService.Interfaces; - using LearningHub.Nhs.Models.Entities.GovNotifyMessaging; - using LearningHub.Nhs.Models.Entities.Hierarchy; + using LearningHub.Nhs.Models.Common; using LearningHub.Nhs.Models.GovNotifyMessaging; using LearningHub.Nhs.OpenApi.Services.Interface.Services.Messaging; - using LearningHub.Nhs.OpenApi.Services.Services.Messaging; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; - using Newtonsoft.Json; /// /// GovNotify Messaging Controller. @@ -156,5 +152,35 @@ public async Task MessageFailedUpdate([FromBody] GovNotifyRespons await this.messageQueueRepository.MessageDeliveryFailed(response); return this.Ok(); } + + /// + /// Get Message Requests. + /// + /// page. + /// page size. + /// sort column name. + /// sort direction. + /// filter. + /// The . + [Route("GetMessageRequests/{page}/{pageSize}/{sortColumn}/{sortDirection}/{filter}")] + [HttpGet] + public async Task GetMessageRequests(int page, int pageSize, string sortColumn, string sortDirection, string filter) + { + PagedResultSet pagedResultSet = await this.govMessageService.GetMessageRequests(page, pageSize, sortColumn, sortDirection, filter); + return this.Ok(pagedResultSet); + } + + /// + /// Get message request details by id. + /// + /// id. + /// The . + [Route("GetMessageRequestById/{id}")] + [HttpGet] + public async Task GetMessageRequestById(int id) + { + MessageRequestViewModel requestDetails = await this.govMessageService.GetMessageRequestById(id); + return this.Ok(requestDetails); + } } } diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj b/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj index 7d5ab0178..59cf60f26 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj @@ -19,7 +19,7 @@ - + diff --git a/ReportAPI/LearningHub.Nhs.ReportApi.Services.Interface/LearningHub.Nhs.ReportApi.Services.Interface.csproj b/ReportAPI/LearningHub.Nhs.ReportApi.Services.Interface/LearningHub.Nhs.ReportApi.Services.Interface.csproj index 79f6af7f9..50db9fa47 100644 --- a/ReportAPI/LearningHub.Nhs.ReportApi.Services.Interface/LearningHub.Nhs.ReportApi.Services.Interface.csproj +++ b/ReportAPI/LearningHub.Nhs.ReportApi.Services.Interface/LearningHub.Nhs.ReportApi.Services.Interface.csproj @@ -16,7 +16,7 @@ - + diff --git a/ReportAPI/LearningHub.Nhs.ReportApi.Services.UnitTests/LearningHub.Nhs.ReportApi.Services.UnitTests.csproj b/ReportAPI/LearningHub.Nhs.ReportApi.Services.UnitTests/LearningHub.Nhs.ReportApi.Services.UnitTests.csproj index c8ca7a2ae..ea5cd2e1f 100644 --- a/ReportAPI/LearningHub.Nhs.ReportApi.Services.UnitTests/LearningHub.Nhs.ReportApi.Services.UnitTests.csproj +++ b/ReportAPI/LearningHub.Nhs.ReportApi.Services.UnitTests/LearningHub.Nhs.ReportApi.Services.UnitTests.csproj @@ -18,7 +18,7 @@ - + diff --git a/ReportAPI/LearningHub.Nhs.ReportApi.Services/LearningHub.Nhs.ReportApi.Services.csproj b/ReportAPI/LearningHub.Nhs.ReportApi.Services/LearningHub.Nhs.ReportApi.Services.csproj index 89bca5ef2..5dace4683 100644 --- a/ReportAPI/LearningHub.Nhs.ReportApi.Services/LearningHub.Nhs.ReportApi.Services.csproj +++ b/ReportAPI/LearningHub.Nhs.ReportApi.Services/LearningHub.Nhs.ReportApi.Services.csproj @@ -19,7 +19,7 @@ - + diff --git a/ReportAPI/LearningHub.Nhs.ReportApi.Shared/LearningHub.Nhs.ReportApi.Shared.csproj b/ReportAPI/LearningHub.Nhs.ReportApi.Shared/LearningHub.Nhs.ReportApi.Shared.csproj index ae1444ed9..37a35de0a 100644 --- a/ReportAPI/LearningHub.Nhs.ReportApi.Shared/LearningHub.Nhs.ReportApi.Shared.csproj +++ b/ReportAPI/LearningHub.Nhs.ReportApi.Shared/LearningHub.Nhs.ReportApi.Shared.csproj @@ -17,7 +17,7 @@ - + diff --git a/ReportAPI/LearningHub.Nhs.ReportApi/LearningHub.Nhs.ReportApi.csproj b/ReportAPI/LearningHub.Nhs.ReportApi/LearningHub.Nhs.ReportApi.csproj index c19afef98..1e3ed8d43 100644 --- a/ReportAPI/LearningHub.Nhs.ReportApi/LearningHub.Nhs.ReportApi.csproj +++ b/ReportAPI/LearningHub.Nhs.ReportApi/LearningHub.Nhs.ReportApi.csproj @@ -20,7 +20,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj b/WebAPI/LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj index 0462105ff..2c379eb4c 100644 --- a/WebAPI/LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj +++ b/WebAPI/LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj @@ -29,7 +29,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Api.Shared/LearningHub.Nhs.Api.Shared.csproj b/WebAPI/LearningHub.Nhs.Api.Shared/LearningHub.Nhs.Api.Shared.csproj index 8d695c492..b3683e53f 100644 --- a/WebAPI/LearningHub.Nhs.Api.Shared/LearningHub.Nhs.Api.Shared.csproj +++ b/WebAPI/LearningHub.Nhs.Api.Shared/LearningHub.Nhs.Api.Shared.csproj @@ -9,7 +9,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/WebAPI/LearningHub.Nhs.Api.UnitTests/LearningHub.Nhs.Api.UnitTests.csproj b/WebAPI/LearningHub.Nhs.Api.UnitTests/LearningHub.Nhs.Api.UnitTests.csproj index 100e6600d..ef48b8165 100644 --- a/WebAPI/LearningHub.Nhs.Api.UnitTests/LearningHub.Nhs.Api.UnitTests.csproj +++ b/WebAPI/LearningHub.Nhs.Api.UnitTests/LearningHub.Nhs.Api.UnitTests.csproj @@ -11,7 +11,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Repository.Interface/LearningHub.Nhs.Repository.Interface.csproj b/WebAPI/LearningHub.Nhs.Repository.Interface/LearningHub.Nhs.Repository.Interface.csproj index 8273e219f..593f2f0ce 100644 --- a/WebAPI/LearningHub.Nhs.Repository.Interface/LearningHub.Nhs.Repository.Interface.csproj +++ b/WebAPI/LearningHub.Nhs.Repository.Interface/LearningHub.Nhs.Repository.Interface.csproj @@ -10,7 +10,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Repository/LearningHub.Nhs.Repository.csproj b/WebAPI/LearningHub.Nhs.Repository/LearningHub.Nhs.Repository.csproj index a2628d76c..1df61ce1c 100644 --- a/WebAPI/LearningHub.Nhs.Repository/LearningHub.Nhs.Repository.csproj +++ b/WebAPI/LearningHub.Nhs.Repository/LearningHub.Nhs.Repository.csproj @@ -9,7 +9,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Services.Interface/LearningHub.Nhs.Services.Interface.csproj b/WebAPI/LearningHub.Nhs.Services.Interface/LearningHub.Nhs.Services.Interface.csproj index 73e99b72e..3c9841066 100644 --- a/WebAPI/LearningHub.Nhs.Services.Interface/LearningHub.Nhs.Services.Interface.csproj +++ b/WebAPI/LearningHub.Nhs.Services.Interface/LearningHub.Nhs.Services.Interface.csproj @@ -16,7 +16,7 @@ - + all diff --git a/WebAPI/LearningHub.Nhs.Services.UnitTests/LearningHub.Nhs.Services.UnitTests.csproj b/WebAPI/LearningHub.Nhs.Services.UnitTests/LearningHub.Nhs.Services.UnitTests.csproj index 6b02d693a..d5b1d8f97 100644 --- a/WebAPI/LearningHub.Nhs.Services.UnitTests/LearningHub.Nhs.Services.UnitTests.csproj +++ b/WebAPI/LearningHub.Nhs.Services.UnitTests/LearningHub.Nhs.Services.UnitTests.csproj @@ -13,7 +13,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Services/LearningHub.Nhs.Services.csproj b/WebAPI/LearningHub.Nhs.Services/LearningHub.Nhs.Services.csproj index d27db0e89..2592a3ed4 100644 --- a/WebAPI/LearningHub.Nhs.Services/LearningHub.Nhs.Services.csproj +++ b/WebAPI/LearningHub.Nhs.Services/LearningHub.Nhs.Services.csproj @@ -13,7 +13,7 @@ - + diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.ConsoleApp/LearningHub.Nhs.Migration.ConsoleApp.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.ConsoleApp/LearningHub.Nhs.Migration.ConsoleApp.csproj index 1a8367ea1..c770b02d6 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.ConsoleApp/LearningHub.Nhs.Migration.ConsoleApp.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.ConsoleApp/LearningHub.Nhs.Migration.ConsoleApp.csproj @@ -25,7 +25,7 @@ - + all diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Interface/LearningHub.Nhs.Migration.Interface.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Interface/LearningHub.Nhs.Migration.Interface.csproj index 56c3518c1..7d52af93a 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Interface/LearningHub.Nhs.Migration.Interface.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Interface/LearningHub.Nhs.Migration.Interface.csproj @@ -9,7 +9,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Models/LearningHub.Nhs.Migration.Models.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Models/LearningHub.Nhs.Migration.Models.csproj index e4a707d63..f4cca3755 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Models/LearningHub.Nhs.Migration.Models.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Models/LearningHub.Nhs.Migration.Models.csproj @@ -10,7 +10,7 @@ - + all diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Staging.Repository/LearningHub.Nhs.Migration.Staging.Repository.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Staging.Repository/LearningHub.Nhs.Migration.Staging.Repository.csproj index a6d13b605..ccec994bb 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Staging.Repository/LearningHub.Nhs.Migration.Staging.Repository.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Staging.Repository/LearningHub.Nhs.Migration.Staging.Repository.csproj @@ -9,7 +9,7 @@ - + diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.UnitTests/LearningHub.Nhs.Migration.UnitTests.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.UnitTests/LearningHub.Nhs.Migration.UnitTests.csproj index 2e25b373f..244e4c832 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.UnitTests/LearningHub.Nhs.Migration.UnitTests.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.UnitTests/LearningHub.Nhs.Migration.UnitTests.csproj @@ -10,7 +10,7 @@ - + diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration/LearningHub.Nhs.Migration.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration/LearningHub.Nhs.Migration.csproj index e21f1b8e1..929806ad3 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration/LearningHub.Nhs.Migration.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration/LearningHub.Nhs.Migration.csproj @@ -12,7 +12,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive From df0cbf44d41a5c5885242561c97d8ab58be62b1f Mon Sep 17 00:00:00 2001 From: Arunima George Date: Mon, 30 Mar 2026 16:58:33 +0100 Subject: [PATCH 13/16] TD-7055: Changed the response format from Open API send email method. --- .../GovNotifyMessagingController.cs | 9 +-- .../SwaggerDefinitions/v1.3.0.json | 81 ++++++++++++++++++- 2 files changed, 83 insertions(+), 7 deletions(-) diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/GovNotifyMessagingController.cs b/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/GovNotifyMessagingController.cs index e7600ff23..64afc8844 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/GovNotifyMessagingController.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/GovNotifyMessagingController.cs @@ -47,13 +47,12 @@ public async Task SendEmailAsync([FromBody] EmailRequest request) { var response = await this.govMessageService.SendEmailAsync(request); - if (!response.IsSuccess) - { - return this.BadRequest(new { error = response.ErrorMessage }); - } + ////if (!response.IsSuccess) + ////{ + //// return this.BadRequest(new { error = response.ErrorMessage }); + ////} return this.Ok(response); - } catch (Exception ex) { diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/SwaggerDefinitions/v1.3.0.json b/OpenAPI/LearningHub.Nhs.OpenApi/SwaggerDefinitions/v1.3.0.json index f2b287be6..95abc6405 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi/SwaggerDefinitions/v1.3.0.json +++ b/OpenAPI/LearningHub.Nhs.OpenApi/SwaggerDefinitions/v1.3.0.json @@ -6174,8 +6174,6 @@ } } } - } - }, }, "/GovNotifyMessage/SendSms": { "post": { @@ -6293,6 +6291,85 @@ } } } + }, + "/GovNotifyMessage/GetMessageRequests/{page}/{pageSize}/{sortColumn}/{sortDirection}/{filter}": { + "post": { + "tags": [ + "GetMessageRequests" + ], + "parameters": [ + { + "name": "page", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "pageSize", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "sortColumn", + "in": "path", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "sortDirection", + "in": "path", + "required": false, + "schema": { + "type": "string" + } + }, + { + "name": "filter", + "in": "path", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/GovNotifyMessage/GetMessageRequestById/{id}": { + "post": { + "tags": [ + "GetMessageRequests" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } } }, "components": { From ca7e26dd754ceac23ca501e6674ea2a9affefd69 Mon Sep 17 00:00:00 2001 From: Arunima George Date: Wed, 8 Apr 2026 17:13:20 +0100 Subject: [PATCH 14/16] Model update --- AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj | 2 +- .../LearningHub.Nhs.WebUI.AutomatedUiTests.csproj | 2 +- LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj | 2 +- .../LearningHub.Nhs.MessageQueueing.csproj | 2 +- .../LearningHub.Nhs.MessagingService.csproj | 2 +- .../LearningHub.Nhs.OpenApi.Models.csproj | 2 +- .../LearningHub.Nhs.OpenApi.Repositories.Interface.csproj | 2 +- .../LearningHub.Nhs.OpenApi.Repositories.csproj | 2 +- .../LearningHub.Nhs.OpenApi.Services.Interface.csproj | 2 +- .../LearningHub.Nhs.OpenApi.Services.csproj | 2 +- .../LearningHub.Nhs.OpenApi.Tests.csproj | 2 +- OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj | 2 +- .../LearningHub.Nhs.ReportApi.Services.Interface.csproj | 2 +- .../LearningHub.Nhs.ReportApi.Services.UnitTests.csproj | 2 +- .../LearningHub.Nhs.ReportApi.Services.csproj | 2 +- .../LearningHub.Nhs.ReportApi.Shared.csproj | 2 +- .../LearningHub.Nhs.ReportApi/LearningHub.Nhs.ReportApi.csproj | 2 +- WebAPI/LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj | 2 +- .../LearningHub.Nhs.Api.Shared.csproj | 2 +- .../LearningHub.Nhs.Api.UnitTests.csproj | 2 +- .../LearningHub.Nhs.Repository.Interface.csproj | 2 +- .../LearningHub.Nhs.Repository.csproj | 2 +- .../LearningHub.Nhs.Services.Interface.csproj | 2 +- .../LearningHub.Nhs.Services.UnitTests.csproj | 2 +- WebAPI/LearningHub.Nhs.Services/LearningHub.Nhs.Services.csproj | 2 +- .../LearningHub.Nhs.Migration.ConsoleApp.csproj | 2 +- .../LearningHub.Nhs.Migration.Interface.csproj | 2 +- .../LearningHub.Nhs.Migration.Models.csproj | 2 +- .../LearningHub.Nhs.Migration.Staging.Repository.csproj | 2 +- .../LearningHub.Nhs.Migration.UnitTests.csproj | 2 +- .../LearningHub.Nhs.Migration/LearningHub.Nhs.Migration.csproj | 2 +- 31 files changed, 31 insertions(+), 31 deletions(-) diff --git a/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj b/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj index 1e0cbbb2d..0b3d434ad 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj +++ b/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj @@ -89,7 +89,7 @@ - + diff --git a/LearningHub.Nhs.WebUI.AutomatedUiTests/LearningHub.Nhs.WebUI.AutomatedUiTests.csproj b/LearningHub.Nhs.WebUI.AutomatedUiTests/LearningHub.Nhs.WebUI.AutomatedUiTests.csproj index 34a9455d2..404a00d6e 100644 --- a/LearningHub.Nhs.WebUI.AutomatedUiTests/LearningHub.Nhs.WebUI.AutomatedUiTests.csproj +++ b/LearningHub.Nhs.WebUI.AutomatedUiTests/LearningHub.Nhs.WebUI.AutomatedUiTests.csproj @@ -13,7 +13,7 @@ - + diff --git a/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj b/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj index 9e1f484cb..cd2698968 100644 --- a/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj +++ b/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj @@ -112,7 +112,7 @@ - + diff --git a/MessageQueueing/LearningHub.Nhs.MessageQueueing/LearningHub.Nhs.MessageQueueing.csproj b/MessageQueueing/LearningHub.Nhs.MessageQueueing/LearningHub.Nhs.MessageQueueing.csproj index a304ded70..3537682c0 100644 --- a/MessageQueueing/LearningHub.Nhs.MessageQueueing/LearningHub.Nhs.MessageQueueing.csproj +++ b/MessageQueueing/LearningHub.Nhs.MessageQueueing/LearningHub.Nhs.MessageQueueing.csproj @@ -7,7 +7,7 @@ - + diff --git a/MessagingService/LearningHub.Nhs.MessagingService/LearningHub.Nhs.MessagingService.csproj b/MessagingService/LearningHub.Nhs.MessagingService/LearningHub.Nhs.MessagingService.csproj index c1bef3c93..2f0e9d58b 100644 --- a/MessagingService/LearningHub.Nhs.MessagingService/LearningHub.Nhs.MessagingService.csproj +++ b/MessagingService/LearningHub.Nhs.MessagingService/LearningHub.Nhs.MessagingService.csproj @@ -8,7 +8,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Models/LearningHub.Nhs.OpenApi.Models.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Models/LearningHub.Nhs.OpenApi.Models.csproj index f93a18aa5..ada20d07f 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Models/LearningHub.Nhs.OpenApi.Models.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Models/LearningHub.Nhs.OpenApi.Models.csproj @@ -17,7 +17,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/LearningHub.Nhs.OpenApi.Repositories.Interface.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/LearningHub.Nhs.OpenApi.Repositories.Interface.csproj index 043795e81..dac1e45d6 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/LearningHub.Nhs.OpenApi.Repositories.Interface.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/LearningHub.Nhs.OpenApi.Repositories.Interface.csproj @@ -17,7 +17,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/LearningHub.Nhs.OpenApi.Repositories.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/LearningHub.Nhs.OpenApi.Repositories.csproj index 29d8422f7..88adf65de 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/LearningHub.Nhs.OpenApi.Repositories.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/LearningHub.Nhs.OpenApi.Repositories.csproj @@ -24,7 +24,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/LearningHub.Nhs.OpenApi.Services.Interface.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/LearningHub.Nhs.OpenApi.Services.Interface.csproj index 4f1227545..dd694a31d 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/LearningHub.Nhs.OpenApi.Services.Interface.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/LearningHub.Nhs.OpenApi.Services.Interface.csproj @@ -17,7 +17,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj index 59dbdf36e..a30dce588 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj @@ -33,7 +33,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Tests/LearningHub.Nhs.OpenApi.Tests.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Tests/LearningHub.Nhs.OpenApi.Tests.csproj index f4251a236..06c0eb51a 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Tests/LearningHub.Nhs.OpenApi.Tests.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Tests/LearningHub.Nhs.OpenApi.Tests.csproj @@ -11,7 +11,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj b/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj index a162b523c..2c3641eb9 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj @@ -19,7 +19,7 @@ - + diff --git a/ReportAPI/LearningHub.Nhs.ReportApi.Services.Interface/LearningHub.Nhs.ReportApi.Services.Interface.csproj b/ReportAPI/LearningHub.Nhs.ReportApi.Services.Interface/LearningHub.Nhs.ReportApi.Services.Interface.csproj index 96ff6ae13..cd760fde6 100644 --- a/ReportAPI/LearningHub.Nhs.ReportApi.Services.Interface/LearningHub.Nhs.ReportApi.Services.Interface.csproj +++ b/ReportAPI/LearningHub.Nhs.ReportApi.Services.Interface/LearningHub.Nhs.ReportApi.Services.Interface.csproj @@ -16,7 +16,7 @@ - + diff --git a/ReportAPI/LearningHub.Nhs.ReportApi.Services.UnitTests/LearningHub.Nhs.ReportApi.Services.UnitTests.csproj b/ReportAPI/LearningHub.Nhs.ReportApi.Services.UnitTests/LearningHub.Nhs.ReportApi.Services.UnitTests.csproj index 70e3e863b..ab77f5198 100644 --- a/ReportAPI/LearningHub.Nhs.ReportApi.Services.UnitTests/LearningHub.Nhs.ReportApi.Services.UnitTests.csproj +++ b/ReportAPI/LearningHub.Nhs.ReportApi.Services.UnitTests/LearningHub.Nhs.ReportApi.Services.UnitTests.csproj @@ -18,7 +18,7 @@ - + diff --git a/ReportAPI/LearningHub.Nhs.ReportApi.Services/LearningHub.Nhs.ReportApi.Services.csproj b/ReportAPI/LearningHub.Nhs.ReportApi.Services/LearningHub.Nhs.ReportApi.Services.csproj index c4944deb0..f39b00693 100644 --- a/ReportAPI/LearningHub.Nhs.ReportApi.Services/LearningHub.Nhs.ReportApi.Services.csproj +++ b/ReportAPI/LearningHub.Nhs.ReportApi.Services/LearningHub.Nhs.ReportApi.Services.csproj @@ -19,7 +19,7 @@ - + diff --git a/ReportAPI/LearningHub.Nhs.ReportApi.Shared/LearningHub.Nhs.ReportApi.Shared.csproj b/ReportAPI/LearningHub.Nhs.ReportApi.Shared/LearningHub.Nhs.ReportApi.Shared.csproj index d02c44881..47cbba31f 100644 --- a/ReportAPI/LearningHub.Nhs.ReportApi.Shared/LearningHub.Nhs.ReportApi.Shared.csproj +++ b/ReportAPI/LearningHub.Nhs.ReportApi.Shared/LearningHub.Nhs.ReportApi.Shared.csproj @@ -17,7 +17,7 @@ - + diff --git a/ReportAPI/LearningHub.Nhs.ReportApi/LearningHub.Nhs.ReportApi.csproj b/ReportAPI/LearningHub.Nhs.ReportApi/LearningHub.Nhs.ReportApi.csproj index 5ad3e0d51..eac5217c6 100644 --- a/ReportAPI/LearningHub.Nhs.ReportApi/LearningHub.Nhs.ReportApi.csproj +++ b/ReportAPI/LearningHub.Nhs.ReportApi/LearningHub.Nhs.ReportApi.csproj @@ -20,7 +20,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj b/WebAPI/LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj index ce240b56f..5ed4ecf86 100644 --- a/WebAPI/LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj +++ b/WebAPI/LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj @@ -29,7 +29,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Api.Shared/LearningHub.Nhs.Api.Shared.csproj b/WebAPI/LearningHub.Nhs.Api.Shared/LearningHub.Nhs.Api.Shared.csproj index 12b019206..c0017cc6f 100644 --- a/WebAPI/LearningHub.Nhs.Api.Shared/LearningHub.Nhs.Api.Shared.csproj +++ b/WebAPI/LearningHub.Nhs.Api.Shared/LearningHub.Nhs.Api.Shared.csproj @@ -9,7 +9,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/WebAPI/LearningHub.Nhs.Api.UnitTests/LearningHub.Nhs.Api.UnitTests.csproj b/WebAPI/LearningHub.Nhs.Api.UnitTests/LearningHub.Nhs.Api.UnitTests.csproj index 70c6f8f9d..c2dd88d3c 100644 --- a/WebAPI/LearningHub.Nhs.Api.UnitTests/LearningHub.Nhs.Api.UnitTests.csproj +++ b/WebAPI/LearningHub.Nhs.Api.UnitTests/LearningHub.Nhs.Api.UnitTests.csproj @@ -11,7 +11,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Repository.Interface/LearningHub.Nhs.Repository.Interface.csproj b/WebAPI/LearningHub.Nhs.Repository.Interface/LearningHub.Nhs.Repository.Interface.csproj index 0ff751617..ba7767177 100644 --- a/WebAPI/LearningHub.Nhs.Repository.Interface/LearningHub.Nhs.Repository.Interface.csproj +++ b/WebAPI/LearningHub.Nhs.Repository.Interface/LearningHub.Nhs.Repository.Interface.csproj @@ -10,7 +10,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Repository/LearningHub.Nhs.Repository.csproj b/WebAPI/LearningHub.Nhs.Repository/LearningHub.Nhs.Repository.csproj index b206c9818..9236b35b8 100644 --- a/WebAPI/LearningHub.Nhs.Repository/LearningHub.Nhs.Repository.csproj +++ b/WebAPI/LearningHub.Nhs.Repository/LearningHub.Nhs.Repository.csproj @@ -9,7 +9,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Services.Interface/LearningHub.Nhs.Services.Interface.csproj b/WebAPI/LearningHub.Nhs.Services.Interface/LearningHub.Nhs.Services.Interface.csproj index 31ce5eb56..e83bb5665 100644 --- a/WebAPI/LearningHub.Nhs.Services.Interface/LearningHub.Nhs.Services.Interface.csproj +++ b/WebAPI/LearningHub.Nhs.Services.Interface/LearningHub.Nhs.Services.Interface.csproj @@ -16,7 +16,7 @@ - + all diff --git a/WebAPI/LearningHub.Nhs.Services.UnitTests/LearningHub.Nhs.Services.UnitTests.csproj b/WebAPI/LearningHub.Nhs.Services.UnitTests/LearningHub.Nhs.Services.UnitTests.csproj index a91b6e0b0..6dea98dfb 100644 --- a/WebAPI/LearningHub.Nhs.Services.UnitTests/LearningHub.Nhs.Services.UnitTests.csproj +++ b/WebAPI/LearningHub.Nhs.Services.UnitTests/LearningHub.Nhs.Services.UnitTests.csproj @@ -13,7 +13,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Services/LearningHub.Nhs.Services.csproj b/WebAPI/LearningHub.Nhs.Services/LearningHub.Nhs.Services.csproj index c44ed1fde..f0079e58c 100644 --- a/WebAPI/LearningHub.Nhs.Services/LearningHub.Nhs.Services.csproj +++ b/WebAPI/LearningHub.Nhs.Services/LearningHub.Nhs.Services.csproj @@ -13,7 +13,7 @@ - + diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.ConsoleApp/LearningHub.Nhs.Migration.ConsoleApp.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.ConsoleApp/LearningHub.Nhs.Migration.ConsoleApp.csproj index a40466948..d5799d6aa 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.ConsoleApp/LearningHub.Nhs.Migration.ConsoleApp.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.ConsoleApp/LearningHub.Nhs.Migration.ConsoleApp.csproj @@ -25,7 +25,7 @@ - + all diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Interface/LearningHub.Nhs.Migration.Interface.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Interface/LearningHub.Nhs.Migration.Interface.csproj index c2ac38a24..ac2ec66db 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Interface/LearningHub.Nhs.Migration.Interface.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Interface/LearningHub.Nhs.Migration.Interface.csproj @@ -9,7 +9,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Models/LearningHub.Nhs.Migration.Models.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Models/LearningHub.Nhs.Migration.Models.csproj index a10f69fd6..8fc39020c 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Models/LearningHub.Nhs.Migration.Models.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Models/LearningHub.Nhs.Migration.Models.csproj @@ -10,7 +10,7 @@ - + all diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Staging.Repository/LearningHub.Nhs.Migration.Staging.Repository.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Staging.Repository/LearningHub.Nhs.Migration.Staging.Repository.csproj index ba2b9fc16..88cef3610 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Staging.Repository/LearningHub.Nhs.Migration.Staging.Repository.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Staging.Repository/LearningHub.Nhs.Migration.Staging.Repository.csproj @@ -9,7 +9,7 @@ - + diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.UnitTests/LearningHub.Nhs.Migration.UnitTests.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.UnitTests/LearningHub.Nhs.Migration.UnitTests.csproj index d555f0d12..076c8717f 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.UnitTests/LearningHub.Nhs.Migration.UnitTests.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.UnitTests/LearningHub.Nhs.Migration.UnitTests.csproj @@ -10,7 +10,7 @@ - + diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration/LearningHub.Nhs.Migration.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration/LearningHub.Nhs.Migration.csproj index c00e268d3..78caf696f 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration/LearningHub.Nhs.Migration.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration/LearningHub.Nhs.Migration.csproj @@ -12,7 +12,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive From 9b495c9cb9ee507a2df7f5d679905771374342c7 Mon Sep 17 00:00:00 2001 From: AnjuJose011 <154979799+AnjuJose011@users.noreply.github.com> Date: Wed, 20 May 2026 15:46:55 +0100 Subject: [PATCH 15/16] conflicts resloved --- .../Services/CatalogueService.cs | 76 +------------------ 1 file changed, 1 insertion(+), 75 deletions(-) diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/CatalogueService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/CatalogueService.cs index 852ee8ef8..ca34d0d84 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/CatalogueService.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/CatalogueService.cs @@ -53,7 +53,6 @@ public class CatalogueService : ICatalogueService private readonly IBookmarkRepository bookmarkRepository; private readonly INodeRepository nodeRepository; private readonly INodeActivityRepository nodeActivityRepository; - private readonly IFindwiseApiFacade findwiseApiFacade; private readonly LearningHubConfig learningHubConfig; private readonly FindwiseConfig findwiseConfig; private readonly INotificationSenderService notificationSenderService; @@ -109,7 +108,6 @@ public CatalogueService( IEmailSenderService emailSenderService, IBookmarkRepository bookmarkRepository, INodeActivityRepository nodeActivityRepository, - IFindwiseApiFacade findwiseApiFacade, INotificationSenderService notificationSenderService, ITimezoneOffsetManager timezoneOffsetManager, ICategoryService categoryService, @@ -132,7 +130,6 @@ public CatalogueService( this.emailSenderService = emailSenderService; this.bookmarkRepository = bookmarkRepository; this.nodeActivityRepository = nodeActivityRepository; - this.findwiseApiFacade = findwiseApiFacade; this.learningHubConfig = learningHubConfig.Value; this.findwiseConfig = findwiseConfig.Value; this.timezoneOffsetManager = timezoneOffsetManager; @@ -660,30 +657,11 @@ public async Task CreateCatalogueAsync(int userId, var catalogueNodeVersionId = await this.catalogueNodeVersionRepository.CreateCatalogueAsync(userId, catalogue); - // Catalogue is in database, push to findwise - var cnv = this.catalogueNodeVersionRepository.GetAll() - .Include(x => x.NodeVersion).ThenInclude(x => x.Node) - .Include(x => x.Keywords) - .Include(x => x.CatalogueNodeVersionProvider) - .SingleOrDefault(x => x.Id == catalogueNodeVersionId); - - if (cnv != null) - { - var searchModel = this.mapper.Map(cnv); - if (searchModel.Description.Length > this.findwiseConfig.DescriptionLengthLimit) - { - searchModel.Description = searchModel.Description.Substring(0, this.findwiseConfig.DescriptionLengthLimit - 4) + "

    "; - } - - await this.findwiseApiFacade.AddOrReplaceAsync(new List { searchModel }); - } - return new LearningHubValidationResult(true) { CreatedId = catalogueNodeVersionId, }; } - /// /// The AddCategoryToCatalogueAsync. /// @@ -894,24 +872,6 @@ public async Task UpdateCatalogueAsync(int userId, await this.catalogueNodeVersionRepository.UpdateCatalogueAsync(userId, catalogue); - // Update catalogue in findwise - var cnv = this.catalogueNodeVersionRepository.GetAll() - .Include(x => x.NodeVersion).ThenInclude(x => x.Node) - .Include(x => x.Keywords) - .Include(x => x.CatalogueNodeVersionProvider) - .SingleOrDefault(x => x.Id == catalogue.CatalogueNodeVersionId); - - if (cnv != null) - { - var searchModel = this.mapper.Map(cnv); - if (searchModel.Description.Length > this.findwiseConfig.DescriptionLengthLimit) - { - searchModel.Description = searchModel.Description.Substring(0, this.findwiseConfig.DescriptionLengthLimit - 4) + "

    "; - } - - await this.findwiseApiFacade.AddOrReplaceAsync(new List { searchModel }); - } - return new LearningHubValidationResult(true); } @@ -938,27 +898,10 @@ public async Task ShowCatalogueAsync(int userId, in await this.catalogueNodeVersionRepository.ShowCatalogue(userId, nodeId); - var cnv = this.catalogueNodeVersionRepository.GetAll() - .Include(x => x.NodeVersion).ThenInclude(x => x.Node) - .Include(x => x.Keywords) - .Include(x => x.CatalogueNodeVersionProvider) - .SingleOrDefault(x => x.NodeVersion.NodeId == nodeId); - - // update findwise - if (cnv != null) - { - var searchModel = this.mapper.Map(cnv); - if (searchModel.Description.Length > this.findwiseConfig.DescriptionLengthLimit) - { - searchModel.Description = searchModel.Description.Substring(0, this.findwiseConfig.DescriptionLengthLimit - 4) + "

    "; - } - - await this.findwiseApiFacade.AddOrReplaceAsync(new List { searchModel }); - } - return new LearningHubValidationResult(true); } + /// /// The ValidateForRestrictedAccess. /// @@ -1012,23 +955,6 @@ public async Task HideCatalogueAsync(int userId, int nodeId) node.Hidden = true; await this.nodeRepository.UpdateAsync(userId, node); - - // update findwise - var cnv = this.catalogueNodeVersionRepository.GetAll() - .Include(x => x.NodeVersion).ThenInclude(x => x.Node) - .Include(x => x.Keywords) - .Include(x => x.CatalogueNodeVersionProvider) - .SingleOrDefault(x => x.NodeVersion.NodeId == nodeId); - if (cnv != null) - { - var searchModel = this.mapper.Map(cnv); - if (searchModel.Description.Length > this.findwiseConfig.DescriptionLengthLimit) - { - searchModel.Description = searchModel.Description.Substring(0, this.findwiseConfig.DescriptionLengthLimit - 4) + "

    "; - } - - await this.findwiseApiFacade.AddOrReplaceAsync(new List { searchModel }); - } } From c57535a91f6010284db291bf955cc8d5fec9d431 Mon Sep 17 00:00:00 2001 From: AnjuJose011 <154979799+AnjuJose011@users.noreply.github.com> Date: Wed, 20 May 2026 15:50:34 +0100 Subject: [PATCH 16/16] conflicts resloved --- .../Services/CatalogueService.cs | 1 + .../Services/Services/CatalogueServiceTests.cs | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/CatalogueService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/CatalogueService.cs index ca34d0d84..ffe5c4a09 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/CatalogueService.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/CatalogueService.cs @@ -92,6 +92,7 @@ public class CatalogueService : ICatalogueService /// emailTemplateService. public CatalogueService( ICatalogueRepository catalogueRepository, + ICategoryService @object, INodeRepository nodeRepository, IUserUserGroupRepository userUserGroupRepository, IMapper mapper, diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Tests/Services/Services/CatalogueServiceTests.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Tests/Services/Services/CatalogueServiceTests.cs index 518a80e78..e17d6effb 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Tests/Services/Services/CatalogueServiceTests.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Tests/Services/Services/CatalogueServiceTests.cs @@ -73,13 +73,13 @@ public CatalogueServiceTests() this.timezoneOffsetManager = new Mock(); this.govMessageSevice = new Mock(); this.emailTemplateService = new Mock(); - this.catalogueService = new CatalogueService(this.catalogueRepository.Object, + this.categoryService = new Mock(); + this.catalogueService = new CatalogueService(this.catalogueRepository.Object, this.categoryService.Object, this.nodeRepository.Object, this.userUserGroupRepository.Object, this.mapper.Object, this.findwiseConfig.Object, this.learningHubConfig.Object, this.catalogueNodeVersionRepository.Object, this.nodeResourceRepository.Object, this.resourceVersionRepository.Object, - this.roleUserGroupRepository.Object, this.providerService.Object, this.catalogueAccessRequestRepository.Object, this.userRepository.Object, this.userProfileRepository.Object, this.emailSenderService.Object, this.bookmarkRepository.Object, this.nodeActivityRepository.Object, this.findwiseApiFacade.Object, this.notificationSenderService.Object, this.timezoneOffsetManager.Object, this.categoryService.Object, this.govMessageSevice.Object, this.emailTemplateService.Object); - this.categoryService = new Mock(); - this.catalogueService = new CatalogueService(this.catalogueRepository.Object, this.categoryService.Object, this.nodeRepository.Object, this.userUserGroupRepository.Object, this.mapper.Object, this.findwiseConfig.Object, this.learningHubConfig.Object, this.catalogueNodeVersionRepository.Object, this.nodeResourceRepository.Object, this.resourceVersionRepository.Object, this.roleUserGroupRepository.Object, this.providerService.Object, this.catalogueAccessRequestRepository.Object, this.userRepository.Object, this.userProfileRepository.Object, this.emailSenderService.Object, this.bookmarkRepository.Object, this.nodeActivityRepository.Object, this.notificationSenderService.Object,this.timezoneOffsetManager.Object); + this.roleUserGroupRepository.Object, this.providerService.Object, this.catalogueAccessRequestRepository.Object, this.userRepository.Object, this.userProfileRepository.Object, this.emailSenderService.Object, this.bookmarkRepository.Object, this.nodeActivityRepository.Object, this.notificationSenderService.Object, this.timezoneOffsetManager.Object, this.categoryService.Object, this.govMessageSevice.Object, this.emailTemplateService.Object); + } private static IEnumerable CatalogueNodeVersionList => new List()