forked from ddrilling/AsbCloudServer
Отправка уведомлений через email + рефакторинг
1. Адаптировал EmailService под сервис транспорта отправки уведомлений по Email 2. Заменил использование EmailService на NotificationService 3. Поправил тесты 4. Создал запрос для отправки уведомлений
This commit is contained in:
parent
8f76a911a2
commit
4b2d4f1bba
@ -17,6 +17,11 @@ public class NotificationDto : IId
|
||||
/// </summary>
|
||||
public int IdUser { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Email получателя уведомления
|
||||
/// </summary>
|
||||
public string? UserEmail { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Id категории уведомления
|
||||
/// </summary>
|
||||
@ -65,6 +70,7 @@ public class NotificationDto : IId
|
||||
/// <summary>
|
||||
/// Id типа доставки уведомления
|
||||
/// 0 - SignalR
|
||||
/// 1 - Email
|
||||
/// </summary>
|
||||
public int IdTransportType { get; set; }
|
||||
|
||||
|
37
AsbCloudApp/Requests/NotifyRequest.cs
Normal file
37
AsbCloudApp/Requests/NotifyRequest.cs
Normal file
@ -0,0 +1,37 @@
|
||||
namespace AsbCloudApp.Requests;
|
||||
|
||||
/// <summary>
|
||||
/// Параметры запроса для отправки уведомления
|
||||
/// </summary>
|
||||
public class NotifyRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// Id пользователя
|
||||
/// </summary>
|
||||
public int IdUser { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Email пользователя
|
||||
/// </summary>
|
||||
public string? UserEmail { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Id категории уведомления. Допустимое значение параметра: 1
|
||||
/// </summary>
|
||||
public int IdNotificationCategory { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Заголовок уведомления
|
||||
/// </summary>
|
||||
public string Title { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Сообщение уведомления
|
||||
/// </summary>
|
||||
public string Message { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Id типа доставки уведомления. Допустимое значение: 0, 1
|
||||
/// </summary>
|
||||
public int IdTransportType { get; set; }
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AsbCloudApp.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Сервис отправки сообщений
|
||||
/// </summary>
|
||||
public interface IEmailService
|
||||
{
|
||||
/// <summary>
|
||||
/// добавить сообщение на отправку нескольким пользователям
|
||||
/// </summary>
|
||||
/// <param name="addresses"></param>
|
||||
/// <param name="subject"></param>
|
||||
/// <param name="htmlBody"></param>
|
||||
void EnqueueSend(IEnumerable<string> addresses, string subject, string htmlBody);
|
||||
|
||||
/// <summary>
|
||||
/// добавить сообщение на отправку одному пользователю
|
||||
/// </summary>
|
||||
/// <param name="address"></param>
|
||||
/// <param name="subject"></param>
|
||||
/// <param name="htmlBody"></param>
|
||||
void EnqueueSend(string address, string subject, string htmlBody);
|
||||
}
|
||||
}
|
@ -33,35 +33,27 @@ public class NotificationService
|
||||
this.notificationRepository = notificationRepository;
|
||||
this.notificationTransportServices = notificationTransportServices;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Отправка нового уведомления
|
||||
/// </summary>
|
||||
/// <param name="idUser"></param>
|
||||
/// <param name="idNotificationCategory"></param>
|
||||
/// <param name="title"></param>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="idTransportType"></param>
|
||||
/// <param name="request"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
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);
|
||||
|
||||
|
@ -103,7 +103,6 @@ namespace AsbCloudInfrastructure
|
||||
|
||||
services.AddMemoryCache();
|
||||
services.AddScoped<IAsbCloudDbContext>(provider => provider.GetRequiredService<AsbCloudDbContext>());
|
||||
services.AddScoped<IEmailService, EmailService>();
|
||||
|
||||
services.AddSingleton(new WitsInfoService());
|
||||
services.AddSingleton(provider => TelemetryDataCache<TelemetryDataSaubDto>.GetInstance<TelemetryDataSaub>(provider));
|
||||
|
@ -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<string, DrillingProgramCreateError> drillingProgramCreateErrors = new Dictionary<string, DrillingProgramCreateError>();
|
||||
|
||||
|
||||
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<IEnumerable<UserDto>> 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<FileCategory> fileCategories, List<AsbCloudDb.Model.FileInfo> files, DrillingProgramPart partEntity, double timezoneOffset)
|
||||
|
@ -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
|
||||
|
@ -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<string> { address }, subject, htmlBody);
|
||||
|
||||
public void EnqueueSend(IEnumerable<string> 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<NotificationDto> notifications, CancellationToken cancellationToken)
|
||||
{
|
||||
var tasks = notifications
|
||||
.Select(notification => SendAsync(notification, cancellationToken));
|
||||
|
||||
return Task.WhenAll(tasks);
|
||||
}
|
||||
|
||||
|
||||
private Func<string, IServiceProvider, CancellationToken, Task> MakeEmailSendWorkAction(IEnumerable<string> addresses, string subject, string htmlBody)
|
||||
{
|
||||
var mailAddresses = new List<MailAddress>();
|
@ -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;
|
||||
}
|
||||
|
||||
///<inheritdoc/>
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<IWellService> wellServiceMock;
|
||||
private readonly Mock<IConfiguration> configurationMock;
|
||||
private readonly Mock<BackgroundWorker> backgroundWorkerMock;
|
||||
private readonly Mock<IEmailService> emailServiceMock;
|
||||
private readonly Mock<NotificationService> notificationServiceMock;
|
||||
|
||||
public DrillingProgramServiceTest()
|
||||
{
|
||||
@ -104,7 +105,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests
|
||||
wellServiceMock = new Mock<IWellService>();
|
||||
configurationMock = new Mock<IConfiguration>();
|
||||
backgroundWorkerMock = new Mock<BackgroundWorker>();
|
||||
emailServiceMock = new Mock<IEmailService>();
|
||||
notificationServiceMock = new Mock<NotificationService>();
|
||||
}
|
||||
|
||||
[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);
|
||||
|
||||
|
@ -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<IUserRepository> userRepositoryMock;
|
||||
private readonly Mock<IWellService> wellServiceMock;
|
||||
private readonly Mock<IEmailService> emailServiceMock;
|
||||
private readonly Mock<IFileCategoryService> fileCategoryService;
|
||||
private readonly NotificationService notificationService;
|
||||
private readonly Mock<ICrudRepository<NotificationCategoryDto>> notificationCategoryRepositoryMock;
|
||||
private readonly Mock<INotificationTransportService> 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<IEmailService>();
|
||||
notificationCategoryRepositoryMock = new Mock<ICrudRepository<NotificationCategoryDto>>();
|
||||
|
||||
notificationCategoryRepositoryMock.Setup(r => r.GetOrDefaultAsync(It.IsAny<int>(),
|
||||
It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new NotificationCategoryDto
|
||||
{
|
||||
Id = 20000,
|
||||
Name = "Системные уведомления"
|
||||
});
|
||||
|
||||
notificationTransportServiceMock = new Mock<INotificationTransportService>();
|
||||
|
||||
notificationTransportServiceMock.SetupGet(x => x.IdTransportType)
|
||||
.Returns(1);
|
||||
|
||||
notificationService = new NotificationService(notificationCategoryRepositoryMock.Object,
|
||||
new Mock<INotificationRepository>().Object,
|
||||
new [] { notificationTransportServiceMock.Object });
|
||||
|
||||
fileCategoryService = new Mock<IFileCategoryService>();
|
||||
fileCategoryService.Setup(s => s.GetOrDefaultAsync(idWellFinalDocCategory, It.IsAny<CancellationToken>()))
|
||||
.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<string>(), It.IsAny<string>(), It.IsAny<string>()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
/// Отправка уведомления
|
||||
/// </summary>
|
||||
/// <param name="idUser">Id пользователя</param>
|
||||
/// <param name="idNotificationCategory">Id категории уведомления. Допустимое значение параметра: 1</param>
|
||||
/// <param name="idNotificationCategory">Id категории уведомления. Допустимые: 1</param>
|
||||
/// <param name="title">Заголовок уведомления</param>
|
||||
/// <param name="message">Сообщение уведомления</param>
|
||||
/// <param name="idNotificationTransport">Id типа доставки уведомления. Допустимое значение: 0</param>
|
||||
/// <param name="idTransportType">Id типа доставки уведомления. Допустимые: 0, 1</param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
[Route("send")]
|
||||
public async Task<IActionResult> 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();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Обновление уведомления
|
||||
/// </summary>
|
||||
@ -78,10 +86,10 @@ public class NotificationController : ControllerBase
|
||||
await notificationService.UpdateNotificationAsync(idNotification,
|
||||
isRead,
|
||||
cancellationToken);
|
||||
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Получение уведомления по Id
|
||||
/// </summary>
|
||||
@ -99,12 +107,12 @@ public class NotificationController : ControllerBase
|
||||
if (notification is null)
|
||||
{
|
||||
return BadRequest(ArgumentInvalidException.MakeValidationError(nameof(idNotification),
|
||||
"Уведомление не найдено"));
|
||||
"Уведомление не найдено"));
|
||||
}
|
||||
|
||||
return Ok(notification);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Получение списка уведомлений
|
||||
/// </summary>
|
||||
@ -121,7 +129,7 @@ public class NotificationController : ControllerBase
|
||||
|
||||
if (!idUser.HasValue)
|
||||
return Forbid();
|
||||
|
||||
|
||||
var result = await notificationRepository.GetNotificationsAsync(idUser.Value,
|
||||
request,
|
||||
cancellationToken);
|
||||
|
@ -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<INotificationTransportService, SignalRNotificationTransportService>();
|
||||
services.AddTransient<INotificationTransportService, EmailNotificationTransportService>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user