From b2cdaf8c81b3a85689ec241e2cba4c6a90e65ccc Mon Sep 17 00:00:00 2001 From: Arunima George Date: Mon, 28 Apr 2025 16:16:58 +0100 Subject: [PATCH 1/3] 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 2/3] 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 3/3] 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),