From 4b2d4f1bba0f48985ecff2f47077b5712672afd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=82=D0=B5=D0=BF=D0=B0=D0=BD=D0=BE=D0=B2=20=D0=94?= =?UTF-8?q?=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=90=D0=BB=D0=B5=D0=BA?= =?UTF-8?q?=D1=81=D0=B0=D0=BD=D0=B4=D1=80=D0=BE=D0=B2=D0=B8=D1=87?= Date: Wed, 19 Jul 2023 14:24:22 +0500 Subject: [PATCH] =?UTF-8?q?=D0=9E=D1=82=D0=BF=D1=80=D0=B0=D0=B2=D0=BA?= =?UTF-8?q?=D0=B0=20=D1=83=D0=B2=D0=B5=D0=B4=D0=BE=D0=BC=D0=BB=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B9=20=D1=87=D0=B5=D1=80=D0=B5=D0=B7=20email=20+=20?= =?UTF-8?q?=D1=80=D0=B5=D1=84=D0=B0=D0=BA=D1=82=D0=BE=D1=80=D0=B8=D0=BD?= =?UTF-8?q?=D0=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Адаптировал EmailService под сервис транспорта отправки уведомлений по Email 2. Заменил использование EmailService на NotificationService 3. Поправил тесты 4. Создал запрос для отправки уведомлений --- AsbCloudApp/Data/NotificationDto.cs | 6 ++ AsbCloudApp/Requests/NotifyRequest.cs | 37 ++++++++++++ AsbCloudApp/Services/IEmailService.cs | 26 --------- .../Notifications/NotificationService.cs | 34 +++++------ AsbCloudInfrastructure/DependencyInjection.cs | 1 - .../DrillingProgram/DrillingProgramService.cs | 57 ++++++++++++++++--- .../Services/Email/DrillingMailBodyFactory.cs | 5 +- ...s => EmailNotificationTransportService.cs} | 47 ++++++++++----- .../Services/WellFinalDocumentsService.cs | 42 ++++++++------ .../DrillingProgramServiceTest.cs | 27 ++++----- .../WellFinalDocumentsServiceTest.cs | 35 ++++++++---- .../Controllers/NotificationController.cs | 48 +++++++++------- AsbCloudWebApi/DependencyInjection.cs | 2 + 13 files changed, 232 insertions(+), 135 deletions(-) create mode 100644 AsbCloudApp/Requests/NotifyRequest.cs delete mode 100644 AsbCloudApp/Services/IEmailService.cs rename AsbCloudInfrastructure/Services/Email/{EmailService.cs => EmailNotificationTransportService.cs} (73%) diff --git a/AsbCloudApp/Data/NotificationDto.cs b/AsbCloudApp/Data/NotificationDto.cs index 982262d2..d699a650 100644 --- a/AsbCloudApp/Data/NotificationDto.cs +++ b/AsbCloudApp/Data/NotificationDto.cs @@ -17,6 +17,11 @@ public class NotificationDto : IId /// public int IdUser { get; set; } + /// + /// Email получателя уведомления + /// + public string? UserEmail { get; set; } + /// /// Id категории уведомления /// @@ -65,6 +70,7 @@ public class NotificationDto : IId /// /// Id типа доставки уведомления /// 0 - SignalR + /// 1 - Email /// public int IdTransportType { get; set; } diff --git a/AsbCloudApp/Requests/NotifyRequest.cs b/AsbCloudApp/Requests/NotifyRequest.cs new file mode 100644 index 00000000..2baf25f1 --- /dev/null +++ b/AsbCloudApp/Requests/NotifyRequest.cs @@ -0,0 +1,37 @@ +namespace AsbCloudApp.Requests; + +/// +/// Параметры запроса для отправки уведомления +/// +public class NotifyRequest +{ + /// + /// Id пользователя + /// + public int IdUser { get; set; } + + /// + /// Email пользователя + /// + public string? UserEmail { get; set; } + + /// + /// Id категории уведомления. Допустимое значение параметра: 1 + /// + public int IdNotificationCategory { get; set; } + + /// + /// Заголовок уведомления + /// + public string Title { get; set; } = null!; + + /// + /// Сообщение уведомления + /// + public string Message { get; set; } = null!; + + /// + /// Id типа доставки уведомления. Допустимое значение: 0, 1 + /// + public int IdTransportType { get; set; } +} \ No newline at end of file diff --git a/AsbCloudApp/Services/IEmailService.cs b/AsbCloudApp/Services/IEmailService.cs deleted file mode 100644 index f1c065f6..00000000 --- a/AsbCloudApp/Services/IEmailService.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Collections.Generic; - -namespace AsbCloudApp.Services -{ - /// - /// Сервис отправки сообщений - /// - public interface IEmailService - { - /// - /// добавить сообщение на отправку нескольким пользователям - /// - /// - /// - /// - void EnqueueSend(IEnumerable addresses, string subject, string htmlBody); - - /// - /// добавить сообщение на отправку одному пользователю - /// - /// - /// - /// - void EnqueueSend(string address, string subject, string htmlBody); - } -} diff --git a/AsbCloudApp/Services/Notifications/NotificationService.cs b/AsbCloudApp/Services/Notifications/NotificationService.cs index 849a2833..afde4ac9 100644 --- a/AsbCloudApp/Services/Notifications/NotificationService.cs +++ b/AsbCloudApp/Services/Notifications/NotificationService.cs @@ -33,35 +33,27 @@ public class NotificationService this.notificationRepository = notificationRepository; this.notificationTransportServices = notificationTransportServices; } - + /// /// Отправка нового уведомления /// - /// - /// - /// - /// - /// + /// /// - /// - public async Task NotifyAsync(int idUser, - int idNotificationCategory, - string title, - string message, - int idTransportType, + public async Task NotifyAsync(NotifyRequest request, CancellationToken cancellationToken) { var notificationCategory = await notificationCategoryRepository - .GetOrDefaultAsync(idNotificationCategory, cancellationToken) - ?? throw new ArgumentInvalidException("Категория уведомления не найдена", nameof(idNotificationCategory)); + .GetOrDefaultAsync(request.IdNotificationCategory, cancellationToken) + ?? throw new ArgumentInvalidException("Категория уведомления не найдена", nameof(request.IdNotificationCategory)); - var notification = new NotificationDto() + var notification = new NotificationDto { - IdUser = idUser, - IdNotificationCategory = idNotificationCategory, - Title = title, - Message = message, - IdTransportType = idTransportType + IdUser = request.IdUser, + UserEmail = request.UserEmail, + IdNotificationCategory = request.IdNotificationCategory, + Title = request.Title, + Message = request.Message, + IdTransportType = request.IdTransportType }; notification.Id = await notificationRepository.InsertAsync(notification, @@ -69,7 +61,7 @@ public class NotificationService notification.NotificationCategory = notificationCategory; - var notificationTransportService = GetNotificationTransportService(idTransportType); + var notificationTransportService = GetNotificationTransportService(request.IdTransportType); await notificationTransportService.SendAsync(notification, cancellationToken); diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs index 6ddc0248..41da11da 100644 --- a/AsbCloudInfrastructure/DependencyInjection.cs +++ b/AsbCloudInfrastructure/DependencyInjection.cs @@ -103,7 +103,6 @@ namespace AsbCloudInfrastructure services.AddMemoryCache(); services.AddScoped(provider => provider.GetRequiredService()); - services.AddScoped(); services.AddSingleton(new WitsInfoService()); services.AddSingleton(provider => TelemetryDataCache.GetInstance(provider)); diff --git a/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs b/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs index 1f41a959..f3e21005 100644 --- a/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs +++ b/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs @@ -16,6 +16,9 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using AsbCloudApp.Requests; +using AsbCloudApp.Services.Notifications; +using AsbCloudInfrastructure.Services.Email; namespace AsbCloudInfrastructure.Services.DrillingProgram { @@ -23,15 +26,18 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram public class DrillingProgramService : IDrillingProgramService { private static readonly Dictionary drillingProgramCreateErrors = new Dictionary(); - + private readonly IAsbCloudDbContext context; private readonly FileService fileService; private readonly IUserRepository userRepository; private readonly IWellService wellService; private readonly IConfiguration configuration; private readonly BackgroundWorker backgroundWorker; - private readonly IEmailService emailService; - + private readonly NotificationService notificationService; + + private const int idNotificationCategory = 20000; + private const int idTransportType = 1; + private const int idFileCategoryDrillingProgram = 1000; private const int idFileCategoryDrillingProgramPartsStart = 1001; private const int idFileCategoryDrillingProgramPartsEnd = 1100; @@ -61,7 +67,7 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram IWellService wellService, IConfiguration configuration, BackgroundWorker backgroundWorker, - IEmailService emailService) + NotificationService notificationService) { this.context = context; this.fileService = fileService; @@ -69,7 +75,7 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram this.wellService = wellService; this.configuration = configuration; this.backgroundWorker = backgroundWorker; - this.emailService = emailService; + this.notificationService = notificationService; } public async Task> GetAvailableUsers(int idWell, CancellationToken token = default) @@ -378,7 +384,15 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram var subject = factory.MakeSubject(well, "Загруженный вами документ полностью согласован"); var body = factory.MakeMailBodyForPublisherOnFullAccept(well, user.Name ?? string.Empty, file.Id, file.Name); - emailService.EnqueueSend(user.Email, subject, body); + await notificationService.NotifyAsync(new NotifyRequest + { + IdUser = user.Id, + UserEmail = user.Email, + IdNotificationCategory = idNotificationCategory, + Title = subject, + Message = body, + IdTransportType = idTransportType + }, token); } private async Task NotifyPublisherOnRejectAsync(FileMarkDto fileMark, CancellationToken token) @@ -393,7 +407,15 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram var subject = factory.MakeSubject(well, "Загруженный вами документ отклонен"); var body = factory.MakeMailBodyForPublisherOnReject(well, user.Name ?? string.Empty, file.Id, file.Name, fileMark); - emailService.EnqueueSend(user.Email, subject, body); + await notificationService.NotifyAsync(new NotifyRequest + { + IdUser = user.Id, + UserEmail = user.Email, + IdNotificationCategory = idNotificationCategory, + Title = subject, + Message = body, + IdTransportType = idTransportType + }, token); } private async Task NotifyApproversAsync(DrillingProgramPart part, int idFile, string fileName, CancellationToken token) @@ -411,7 +433,15 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram foreach (var user in users) { var body = factory.MakeMailBodyForApproverNewFile(well, user.Name ?? string.Empty, idFile, fileName); - emailService.EnqueueSend(user.Email, subject, body); + await notificationService.NotifyAsync(new NotifyRequest + { + IdUser = user.Id, + UserEmail = user.Email, + IdNotificationCategory = idNotificationCategory, + Title = subject, + Message = body, + IdTransportType = idTransportType + }, token); } } @@ -424,7 +454,16 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram var factory = new DrillingMailBodyFactory(configuration); var subject = factory.MakeSubject(well, $"От вас ожидается загрузка на портал документа «{documentCategory}»"); var body = factory.MakeMailBodyForNewPublisher(well, user.Name ?? string.Empty, documentCategory); - emailService.EnqueueSend(user.Email, subject, body); + + await notificationService.NotifyAsync(new NotifyRequest + { + IdUser = user.Id, + UserEmail = user.Email, + IdNotificationCategory = idNotificationCategory, + Title = subject, + Message = body, + IdTransportType = idTransportType + }, token); } private static DrillingProgramPartDto ConvertPart(int idUser, List fileCategories, List files, DrillingProgramPart partEntity, double timezoneOffset) diff --git a/AsbCloudInfrastructure/Services/Email/DrillingMailBodyFactory.cs b/AsbCloudInfrastructure/Services/Email/DrillingMailBodyFactory.cs index d6a4a9da..ba0da560 100644 --- a/AsbCloudInfrastructure/Services/Email/DrillingMailBodyFactory.cs +++ b/AsbCloudInfrastructure/Services/Email/DrillingMailBodyFactory.cs @@ -1,10 +1,7 @@ using AsbCloudApp.Data; -using AsbCloudInfrastructure.Services.Email; using Microsoft.Extensions.Configuration; -using System; -using System.IO; -namespace AsbCloudInfrastructure +namespace AsbCloudInfrastructure.Services.Email { class DrillingMailBodyFactory : BaseFactory diff --git a/AsbCloudInfrastructure/Services/Email/EmailService.cs b/AsbCloudInfrastructure/Services/Email/EmailNotificationTransportService.cs similarity index 73% rename from AsbCloudInfrastructure/Services/Email/EmailService.cs rename to AsbCloudInfrastructure/Services/Email/EmailNotificationTransportService.cs index d4d4e94f..01fb94ff 100644 --- a/AsbCloudInfrastructure/Services/Email/EmailService.cs +++ b/AsbCloudInfrastructure/Services/Email/EmailNotificationTransportService.cs @@ -1,19 +1,20 @@ -using AsbCloudApp.Exceptions; -using AsbCloudApp.Services; -using Microsoft.Extensions.Configuration; -using System; +using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net.Mail; using System.Threading; using System.Threading.Tasks; +using AsbCloudApp.Data; +using AsbCloudApp.Exceptions; +using AsbCloudApp.Services.Notifications; using AsbCloudInfrastructure.Background; +using Microsoft.Extensions.Configuration; -namespace AsbCloudInfrastructure.Services +namespace AsbCloudInfrastructure.Services.Email { - public class EmailService : IEmailService + public class EmailNotificationTransportService : INotificationTransportService { private readonly BackgroundWorker backgroundWorker; private readonly bool IsConfigured; @@ -21,7 +22,8 @@ namespace AsbCloudInfrastructure.Services private readonly string smtpServer; private readonly string smtpPassword; - public EmailService(BackgroundWorker backgroundWorker, IConfiguration configuration) + public EmailNotificationTransportService(BackgroundWorker backgroundWorker, + IConfiguration configuration) { sender = configuration.GetValue("email:sender", string.Empty); smtpPassword = configuration.GetValue("email:password", string.Empty); @@ -36,25 +38,42 @@ namespace AsbCloudInfrastructure.Services this.backgroundWorker = backgroundWorker; } - public void EnqueueSend(string address, string subject, string htmlBody) - => EnqueueSend(new List { address }, subject, htmlBody); - - public void EnqueueSend(IEnumerable addresses, string subject, string htmlBody) + public int IdTransportType => 1; + + public Task SendAsync(NotificationDto notification, CancellationToken cancellationToken) { if (!IsConfigured) { Trace.TraceWarning("smtp is not configured"); - return; + return Task.CompletedTask; } - var workId = MakeWorkId(addresses, subject, htmlBody); + + if (string.IsNullOrWhiteSpace(notification.UserEmail)) + { + Trace.TraceWarning("User email is not null"); + return Task.CompletedTask; + } + + var workId = MakeWorkId(new []{ notification.UserEmail }, notification.Title, notification.Message); if (!backgroundWorker.Contains(workId)) { - var workAction = MakeEmailSendWorkAction(addresses, subject, htmlBody); + var workAction = MakeEmailSendWorkAction(new []{ notification.UserEmail }, notification.Title, notification.Message); var work = new WorkBase(workId, workAction); backgroundWorker.Push(work); } + + return Task.CompletedTask; } + public Task SendRangeAsync(IEnumerable notifications, CancellationToken cancellationToken) + { + var tasks = notifications + .Select(notification => SendAsync(notification, cancellationToken)); + + return Task.WhenAll(tasks); + } + + private Func MakeEmailSendWorkAction(IEnumerable addresses, string subject, string htmlBody) { var mailAddresses = new List(); diff --git a/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs b/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs index 373e2433..a221de84 100644 --- a/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs +++ b/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs @@ -10,6 +10,7 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using AsbCloudApp.Services.Notifications; namespace AsbCloudInfrastructure.Services { @@ -23,9 +24,9 @@ namespace AsbCloudInfrastructure.Services private readonly IUserRepository userRepository; private readonly IWellService wellService; private readonly IConfiguration configuration; - private readonly IEmailService emailService; private readonly IFileCategoryService fileCategoryService; private readonly IWellFinalDocumentsRepository wellFinalDocumentsRepository; + private readonly NotificationService notificationService; private const int FileServiceThrewException = -1; @@ -33,17 +34,17 @@ namespace AsbCloudInfrastructure.Services IUserRepository userRepository, IWellService wellService, IConfiguration configuration, - IEmailService emailService, IFileCategoryService fileCategoryService, - IWellFinalDocumentsRepository wellFinalDocumentsRepository) + IWellFinalDocumentsRepository wellFinalDocumentsRepository, + NotificationService notificationService) { this.fileService = fileService; this.userRepository = userRepository; this.wellService = wellService; this.configuration = configuration; - this.emailService = emailService; this.fileCategoryService = fileCategoryService; this.wellFinalDocumentsRepository = wellFinalDocumentsRepository; + this.notificationService = notificationService; } /// @@ -129,27 +130,36 @@ namespace AsbCloudInfrastructure.Services if(well is null) throw new ArgumentInvalidException("idWell doesn`t exist", nameof(item.IdWell)); - SendMessage(well, user, category?.Name ?? string.Empty, message); + await SendMessageAsync(well, user, category?.Name ?? string.Empty, message, + token); } } } - private void SendMessage(WellDto well, UserDto user, string documentCategory, string message) + private async Task SendMessageAsync(WellDto well, UserDto user, string documentCategory, string message, + CancellationToken cancellationToken) { + const int idNotificationCategory = 20000; + const int idTransportType = 1; + var factory = new WellFinalDocumentMailBodyFactory(configuration); var subject = factory.MakeSubject(well, documentCategory); - if(!string.IsNullOrEmpty(user.Email)) - { - var body = factory.MakeMailBodyForWellFinalDocument( - well, - (user.Name ?? user.Surname ?? string.Empty), - string.Format(message, documentCategory) - ); + var body = factory.MakeMailBodyForWellFinalDocument( + well, + (user.Name ?? user.Surname ?? string.Empty), + string.Format(message, documentCategory) + ); - emailService.EnqueueSend(user.Email, subject, body); - } - + await notificationService.NotifyAsync(new NotifyRequest + { + IdUser = user.Id, + UserEmail = user.Email, + IdNotificationCategory = idNotificationCategory, + Title = subject, + Message = body, + IdTransportType = idTransportType + }, cancellationToken); } } diff --git a/AsbCloudWebApi.Tests/ServicesTests/DrillingProgramServiceTest.cs b/AsbCloudWebApi.Tests/ServicesTests/DrillingProgramServiceTest.cs index 751013bb..12bc81a2 100644 --- a/AsbCloudWebApi.Tests/ServicesTests/DrillingProgramServiceTest.cs +++ b/AsbCloudWebApi.Tests/ServicesTests/DrillingProgramServiceTest.cs @@ -13,6 +13,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using AsbCloudApp.Services.Notifications; using Xunit; namespace AsbCloudWebApi.Tests.ServicesTests @@ -85,7 +86,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests private readonly Mock wellServiceMock; private readonly Mock configurationMock; private readonly Mock backgroundWorkerMock; - private readonly Mock emailServiceMock; + private readonly Mock notificationServiceMock; public DrillingProgramServiceTest() { @@ -104,7 +105,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests wellServiceMock = new Mock(); configurationMock = new Mock(); backgroundWorkerMock = new Mock(); - emailServiceMock = new Mock(); + notificationServiceMock = new Mock(); } [Fact] @@ -117,7 +118,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests wellServiceMock.Object, configurationMock.Object, backgroundWorkerMock.Object, - emailServiceMock.Object); + notificationServiceMock.Object); var users = await service.GetAvailableUsers(idWell, CancellationToken.None); @@ -134,7 +135,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests wellServiceMock.Object, configurationMock.Object, backgroundWorkerMock.Object, - emailServiceMock.Object); + notificationServiceMock.Object); var result = await service.AddPartsAsync(idWell, new int[] { 1001, 1002 }, CancellationToken.None); @@ -153,7 +154,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests wellServiceMock.Object, configurationMock.Object, backgroundWorkerMock.Object, - emailServiceMock.Object); + notificationServiceMock.Object); var result = await service.RemovePartsAsync(idWell, new int[] { 1005 }, CancellationToken.None); @@ -176,7 +177,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests wellServiceMock.Object, configurationMock.Object, backgroundWorkerMock.Object, - emailServiceMock.Object); + notificationServiceMock.Object); var result = await service.AddUserAsync(idWell, 1001, publisher1.Id, 1, CancellationToken.None); @@ -211,7 +212,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests wellServiceMock.Object, configurationMock.Object, backgroundWorkerMock.Object, - emailServiceMock.Object); + notificationServiceMock.Object); var result = await service.RemoveUserAsync(idWell, idFileCategory, publisher1.Id, idUserRole, CancellationToken.None); @@ -237,7 +238,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests wellServiceMock.Object, configurationMock.Object, backgroundWorkerMock.Object, - emailServiceMock.Object); + notificationServiceMock.Object); var fileMark = new FileMarkDto { @@ -268,7 +269,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests wellServiceMock.Object, configurationMock.Object, backgroundWorkerMock.Object, - emailServiceMock.Object); + notificationServiceMock.Object); var fileMark = new FileMarkDto { IdFile = file1001.Id, @@ -306,7 +307,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests wellServiceMock.Object, configurationMock.Object, backgroundWorkerMock.Object, - emailServiceMock.Object); + notificationServiceMock.Object); var fileMark = new FileMarkDto { @@ -333,7 +334,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests wellServiceMock.Object, configurationMock.Object, backgroundWorkerMock.Object, - emailServiceMock.Object); + notificationServiceMock.Object); var state = await service.GetStateAsync(idWell, publisher1.Id, CancellationToken.None); @@ -360,7 +361,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests wellServiceMock.Object, configurationMock.Object, backgroundWorkerMock.Object, - emailServiceMock.Object); + notificationServiceMock.Object); var state = await service.GetStateAsync(idWell, publisher1.Id, CancellationToken.None); @@ -390,7 +391,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests wellServiceMock.Object, configurationMock.Object, backgroundWorkerMock.Object, - emailServiceMock.Object); + notificationServiceMock.Object); var state = await service.GetStateAsync(idWell, publisher1.Id, CancellationToken.None); diff --git a/AsbCloudWebApi.Tests/ServicesTests/WellFinalDocumentsServiceTest.cs b/AsbCloudWebApi.Tests/ServicesTests/WellFinalDocumentsServiceTest.cs index e6ae7a4a..fda6e0f9 100644 --- a/AsbCloudWebApi.Tests/ServicesTests/WellFinalDocumentsServiceTest.cs +++ b/AsbCloudWebApi.Tests/ServicesTests/WellFinalDocumentsServiceTest.cs @@ -10,6 +10,7 @@ using System.Linq; using AsbCloudApp.Repositories; using System.Collections.Generic; using AsbCloudApp.Data.User; +using AsbCloudApp.Services.Notifications; namespace AsbCloudWebApi.Tests.ServicesTests { @@ -21,8 +22,10 @@ namespace AsbCloudWebApi.Tests.ServicesTests private readonly WellFinalDocumentsService service; private readonly Mock userRepositoryMock; private readonly Mock wellServiceMock; - private readonly Mock emailServiceMock; private readonly Mock fileCategoryService; + private readonly NotificationService notificationService; + private readonly Mock> notificationCategoryRepositoryMock; + private readonly Mock notificationTransportServiceMock; private static readonly UserExtendedDto[] users = new[]{ new UserExtendedDto { @@ -126,7 +129,25 @@ namespace AsbCloudWebApi.Tests.ServicesTests Deposit = "deposit 1" }); var configuration = new Microsoft.Extensions.Configuration.ConfigurationBuilder().Build(); - emailServiceMock = new Mock(); + notificationCategoryRepositoryMock = new Mock>(); + + notificationCategoryRepositoryMock.Setup(r => r.GetOrDefaultAsync(It.IsAny(), + It.IsAny())) + .ReturnsAsync(new NotificationCategoryDto + { + Id = 20000, + Name = "Системные уведомления" + }); + + notificationTransportServiceMock = new Mock(); + + notificationTransportServiceMock.SetupGet(x => x.IdTransportType) + .Returns(1); + + notificationService = new NotificationService(notificationCategoryRepositoryMock.Object, + new Mock().Object, + new [] { notificationTransportServiceMock.Object }); + fileCategoryService = new Mock(); fileCategoryService.Setup(s => s.GetOrDefaultAsync(idWellFinalDocCategory, It.IsAny())) .ReturnsAsync((int id, CancellationToken _) => new FileCategoryDto @@ -140,7 +161,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests userRepository: userRepositoryMock.Object, wellService: wellServiceMock.Object, configuration: configuration, - emailService: emailServiceMock.Object, + notificationService: notificationService, fileCategoryService: fileCategoryService.Object, wellFinalDocumentsRepository: wellFinalDocumentsRepository.Object); } @@ -187,13 +208,5 @@ namespace AsbCloudWebApi.Tests.ServicesTests var data = await service.ReNotifyPublishersAsync(1, users[0].Id, idWellFinalDocCategory, CancellationToken.None); Assert.Equal(1, data); } - - [Fact] - public async Task ReNotifyPublishersAsync_returns_2() - { - var emailsCount = await service.ReNotifyPublishersAsync(1, users[0].Id, idWellFinalDocCategory, CancellationToken.None); - Assert.Equal(1, emailsCount); - emailServiceMock.Verify(s => s.EnqueueSend(It.IsAny(), It.IsAny(), It.IsAny())); - } } } diff --git a/AsbCloudWebApi/Controllers/NotificationController.cs b/AsbCloudWebApi/Controllers/NotificationController.cs index 2e1bb976..61224f31 100644 --- a/AsbCloudWebApi/Controllers/NotificationController.cs +++ b/AsbCloudWebApi/Controllers/NotificationController.cs @@ -19,12 +19,15 @@ namespace AsbCloudWebApi.Controllers; [Route("api/notification")] public class NotificationController : ControllerBase { + private readonly IUserRepository userRepository; private readonly NotificationService notificationService; private readonly INotificationRepository notificationRepository; - public NotificationController(NotificationService notificationService, + public NotificationController(IUserRepository userRepository, + NotificationService notificationService, INotificationRepository notificationRepository) { + this.userRepository = userRepository; this.notificationService = notificationService; this.notificationRepository = notificationRepository; } @@ -33,35 +36,40 @@ public class NotificationController : ControllerBase /// Отправка уведомления /// /// Id пользователя - /// Id категории уведомления. Допустимое значение параметра: 1 + /// Id категории уведомления. Допустимые: 1 /// Заголовок уведомления /// Сообщение уведомления - /// Id типа доставки уведомления. Допустимое значение: 0 + /// Id типа доставки уведомления. Допустимые: 0, 1 /// /// [HttpPost] [Route("send")] public async Task SendAsync([Required] int idUser, - [Required] - [Range(minimum: 1, maximum: 1, ErrorMessage = "Id категории уведомления недоступно. Допустимые: 1")] + [Required] [Range(minimum: 1, maximum: 1, ErrorMessage = "Id категории уведомления недоступно. Допустимые: 1")] int idNotificationCategory, [Required] string title, [Required] string message, [Required] - [Range(minimum: 0, maximum: 0, ErrorMessage = "Id способа отправки уведомления недоступно. Допустимые: 0")] - int idNotificationTransport, + [Range(minimum: 0, maximum: 1, ErrorMessage = "Id способа отправки уведомления недоступно. Допустимые: 0, 1")] + int idTransportType, CancellationToken cancellationToken) { - await notificationService.NotifyAsync(idUser, - idNotificationCategory, - title, - message, - idNotificationTransport, - cancellationToken); - + var user = await userRepository.GetOrDefaultAsync(idUser, cancellationToken) + ?? throw new ArgumentInvalidException("Пользователь не найден", nameof(idUser)); + + await notificationService.NotifyAsync(new NotifyRequest + { + IdUser = user.Id, + UserEmail = user.Email, + IdNotificationCategory = idNotificationCategory, + Title = title, + Message = message, + IdTransportType = idTransportType + }, cancellationToken); + return Ok(); } - + /// /// Обновление уведомления /// @@ -78,10 +86,10 @@ public class NotificationController : ControllerBase await notificationService.UpdateNotificationAsync(idNotification, isRead, cancellationToken); - + return Ok(); } - + /// /// Получение уведомления по Id /// @@ -99,12 +107,12 @@ public class NotificationController : ControllerBase if (notification is null) { return BadRequest(ArgumentInvalidException.MakeValidationError(nameof(idNotification), - "Уведомление не найдено")); + "Уведомление не найдено")); } return Ok(notification); } - + /// /// Получение списка уведомлений /// @@ -121,7 +129,7 @@ public class NotificationController : ControllerBase if (!idUser.HasValue) return Forbid(); - + var result = await notificationRepository.GetNotificationsAsync(idUser.Value, request, cancellationToken); diff --git a/AsbCloudWebApi/DependencyInjection.cs b/AsbCloudWebApi/DependencyInjection.cs index 7477f745..f64f5b2c 100644 --- a/AsbCloudWebApi/DependencyInjection.cs +++ b/AsbCloudWebApi/DependencyInjection.cs @@ -13,6 +13,7 @@ using System.IO; using System.Reflection; using System.Threading.Tasks; using AsbCloudApp.Services.Notifications; +using AsbCloudInfrastructure.Services.Email; using AsbCloudWebApi.SignalR.Services; using Microsoft.OpenApi.Any; @@ -139,6 +140,7 @@ namespace AsbCloudWebApi public static void AddNotificationTransportServices(this IServiceCollection services) { services.AddTransient(); + services.AddTransient(); } } }