diff --git a/AsbCloudApp/Services/IEmailService.cs b/AsbCloudApp/Services/IEmailService.cs index 011cb33a..a196ca03 100644 --- a/AsbCloudApp/Services/IEmailService.cs +++ b/AsbCloudApp/Services/IEmailService.cs @@ -5,5 +5,6 @@ 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/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj b/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj index 529cfdb4..f804191b 100644 --- a/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj +++ b/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj @@ -53,4 +53,10 @@ + + + PreserveNewest + + + diff --git a/AsbCloudInfrastructure/Services/Email/logo_32.png b/AsbCloudInfrastructure/Res/logo_32.png similarity index 100% rename from AsbCloudInfrastructure/Services/Email/logo_32.png rename to AsbCloudInfrastructure/Res/logo_32.png diff --git a/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs b/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs index d53797cb..44b88f06 100644 --- a/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs +++ b/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs @@ -24,7 +24,6 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram private readonly IWellService wellService; private readonly IConfiguration configuration; private readonly IBackgroundWorkerService backgroundWorker; - //email private readonly IEmailService emailService; private readonly string connectionString; @@ -158,12 +157,12 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram await TryEnqueueMakeProgramAsync(idWell, state, token); return state; } - - + public async Task AddFile(int idWell, int idFileCategory, int idUser, string fileFullName, System.IO.Stream fileStream, CancellationToken token = default) { var part = await context.DrillingProgramParts .Include(p => p.RelatedUsers) + .ThenInclude(r => r.User) .FirstOrDefaultAsync(p => p.IdWell == idWell && p.IdFileCategory == idFileCategory, token); if (part == null) @@ -181,35 +180,9 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram token); await RemoveDrillingProgramAsync(part.IdWell, token); - var well = await context.Wells - .FirstOrDefaultAsync(x => x.Id == idWell, token); - var cluster = await context.Clusters - .FirstOrDefaultAsync(x => x.Wells == well, token); - - var deposit = await context.Deposits - .FirstOrDefaultAsync(x => x.Clusters == cluster, token); - var partApprovers = await context.RelationDrillingProgramPartUsers - .Where(y => y.IdDrillingProgramPart == part.Id & y.IdUserRole == idUserRoleApprover).ToListAsync(token); - foreach (var partApprover in partApprovers) - { - var approver = await context.Users - .FirstOrDefaultAsync(x => x.Id == partApprover.IdUser, token); - var bodyHtml = new MailCoordinating() - { - idWell=idWell, - idDocument = result.Id, - documentName = fileFullName, - wellName = well.Caption, - clusterName = cluster.Caption, - fieldName = deposit.Caption, - userName = $"{approver.Name} {approver.Surname}" + await NotifyApproversAsync(part, result.Id, fileFullName, token); - - }; - emailService.EnqueueSend(new List {approver.Email}, bodyHtml.mailSubject, bodyHtml.GetBodyHTML()); - //emailService.EnqueueSend(new List { "79827873134@yandex.ru" }, bodyHtml.mailSubject, bodyHtml.GetBodyHTML()); - } return result.Id; } @@ -256,6 +229,7 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram throw new ArgumentInvalidException($"User id == {idUser} does not exist", nameof(idUser)); var part = await context.DrillingProgramParts + .Include(p=>p.FileCategory) .FirstOrDefaultAsync(p => p.IdWell == idWell && p.IdFileCategory == idFileCategory, token); if (part is null) @@ -276,35 +250,12 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram IdDrillingProgramPart = part.Id, IdUserRole = idUserRole, }; - var well = await context.Wells - .FirstOrDefaultAsync(x => x.Id == idWell, token); - var cluster = await context.Clusters - .FirstOrDefaultAsync(x => x.Wells == well, token); - context.RelationDrillingProgramPartUsers.Add(newRelation); - var deposit = await context.Deposits - .FirstOrDefaultAsync(x => x.Clusters == cluster, token); - var documentCategory = await context.FileCategories - .FirstOrDefaultAsync(x => x.Id == part.IdFileCategory, token); context.RelationDrillingProgramPartUsers.Add(newRelation); if (idUserRole == idUserRoleApprover) await RemoveDrillingProgramAsync(part.IdWell, token); - // проверяем роль пользователя - если публикатор формируем для него сообщение на отправку - if (idUserRole == idUserRolePublisher) - { - //создаем тело письма - var bodyHtml = new MailUserPublisher() - { - idWell=idWell, - userName = $"{user.Name} {user.Surname}", - wellName = well.Caption, - clusterName = cluster.Caption, - fieldName = deposit.Caption, - documentCategory = documentCategory.Name - }; - emailService.EnqueueSend(new List {user.Email}, bodyHtml.mailSubject, bodyHtml.GetBodyHTML()); - //emailService.EnqueueSend(new List { "79827873134@yandex.ru" }, bodyHtml.mailSubject, bodyHtml.GetBodyHTML()); - } + await NotifyNewPublisherAsync(idWell, user, part.FileCategory.Name, token); + return await context.SaveChangesAsync(token); } @@ -322,9 +273,6 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram return await context.SaveChangesAsync(token); } - // 4 trigger?? - - public async Task AddOrReplaceFileMarkAsync(FileMarkDto fileMarkDto, int idUser, CancellationToken token) { if (fileMarkDto.IdMarkType != idMarkTypeApprove && @@ -361,73 +309,18 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram if (fileMarkDto.IdMarkType == idMarkTypeReject) { await RemoveDrillingProgramAsync(fileInfo.IdWell, token); - - var user = await context.Users - .FirstOrDefaultAsync(x => x.Id == idUser, token); - var well = await context.Wells - .FirstOrDefaultAsync(x => x.Id == part.IdWell, token); - var cluster = await context.Clusters - .FirstOrDefaultAsync(x => x.Wells == well, token); - - var deposit = await context.Deposits - .FirstOrDefaultAsync(x => x.Clusters == cluster, token); - var document = await context.Files - .FirstOrDefaultAsync(x => x.Id == fileMarkDto.IdFile, token); - var author = await context.Users - .FirstOrDefaultAsync(x => x.Id == document.IdAuthor, token); - - var bodyHtml = new PublisherRejected - { - idWell=well.Id, - idDocument=document.Id, - coordinatingName = $"{user.Name} {user.Surname}", - coordinatingComment = fileMarkDto.Comment, - wellName = well.Caption, - clusterName = cluster.Caption, - fieldName = deposit.Caption, - documentName = document.Name, - userName = $"{author.Name} {author.Surname}" - }; - - emailService.EnqueueSend(new List { author.Email }, bodyHtml.mailSubject, bodyHtml.GetBodyHTML()); - //emailService.EnqueueSend(new List { "79827873134@yandex.ru" }, bodyHtml.mailSubject, bodyHtml.GetBodyHTML()); + await NotifyPublisherOnRejectAsync(fileMarkDto, token); } - // если все части согласованы уведомляем публикатора + // если все согласованты согласовали - оповещаем публикатора if (part.RelatedUsers .Where(u => u.IdUserRole == idUserRoleApprover) .All(user => fileInfo.FileMarks .Any(mark => mark.IdMarkType == idMarkTypeApprove && mark.User.Id == user.IdUser))) { - var well = await context.Wells - .FirstOrDefaultAsync(x => x.Id == part.IdWell, token); - var cluster = await context.Clusters - .FirstOrDefaultAsync(x => x.Wells == well, token); - - var deposit = await context.Deposits - .FirstOrDefaultAsync(x => x.Clusters == cluster, token); - var document = await context.Files - .FirstOrDefaultAsync(x => x.Id == fileMarkDto.IdFile, token); - var author = await context.Users - .FirstOrDefaultAsync(x => x.Id == document.IdAuthor, token); - var documentCategory = await context.FileCategories - .FirstOrDefaultAsync(x => x.Id == part.IdFileCategory, token); - var bodyHtml = new AllApprovals - { - idWell=well.Id, - idDocument=document.Id, - documentCategory = documentCategory.Name, - wellName = well.Caption, - clusterName = cluster.Caption, - fieldName = deposit.Caption, - documentName = document.Name, - userName = $"{author.Name} {author.Surname}" - }; - emailService.EnqueueSend(new List { author.Email }, bodyHtml.mailSubject, bodyHtml.GetBodyHTML()); - //emailService.EnqueueSend(new List { "79827873134@yandex.ru" }, bodyHtml.mailSubject, bodyHtml.GetBodyHTML()); + await NotifyPublisherOnFullAccepAsync(fileMarkDto, token); } - return result; } @@ -448,6 +341,55 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram return result; } + private async Task NotifyPublisherOnFullAccepAsync(FileMarkDto fileMark, CancellationToken token) + { + var file = await fileService.GetInfoAsync(fileMark.IdFile, token); + var well = await wellService.GetAsync(file.IdWell, token); + var user = file.Author; + var factory = new MailBodyFactory(configuration); + var subject = MailBodyFactory.MakeSubject(well, "Загруженный вами документ полностью согласован"); + var body = factory.MakeMailBodyForPublisherOnFullAccept(well, user.Name, file.Id, file.Name); + + emailService.EnqueueSend(user.Email, subject, body); + } + + private async Task NotifyPublisherOnRejectAsync(FileMarkDto fileMark, CancellationToken token) + { + var file = await fileService.GetInfoAsync(fileMark.IdFile, token); + var well = await wellService.GetAsync(file.IdWell, token); + var user = file.Author; + var factory = new MailBodyFactory(configuration); + var subject = MailBodyFactory.MakeSubject(well, "Загруженный вами документ отклонен"); + var body = factory.MakeMailBodyForPublisherOnReject(well, user.Name, file.Id, file.Name, fileMark); + + emailService.EnqueueSend(user.Email, subject, body); + } + + private async Task NotifyApproversAsync(DrillingProgramPart part, int idFile, string fileName, CancellationToken token) + { + var well = await wellService.GetAsync(part.IdWell, token); + var factory = new MailBodyFactory(configuration); + var subject = MailBodyFactory.MakeSubject(well, "Загружен новый документ для согласования."); + var users = part.RelatedUsers + .Where(r => r.IdUserRole == idUserRoleApprover) + .Select(r => r.User); + + foreach (var user in users) + { + var body = factory.MakeMailBodyForApproverNewFile(well, user.Name, idFile, fileName); + emailService.EnqueueSend(user.Email, subject, body); + } + } + + private async Task NotifyNewPublisherAsync(int idWell, UserDto user, string documentCategory, CancellationToken token) + { + var well = await wellService.GetAsync(idWell, token); + var factory = new MailBodyFactory(configuration); + var subject = MailBodyFactory.MakeSubject(well, $"От вас ожидается загрузка на портал документа «{documentCategory}»"); + var body = factory.MakeMailBodyForNewPublisher(well, user.Name, documentCategory); + emailService.EnqueueSend(user.Email, subject, body); + } + private DrillingProgramPartDto ConvertPart(int idUser, List fileCategories, List files, DrillingProgramPart partEntity, double timezoneOffset) { var part = new DrillingProgramPartDto diff --git a/AsbCloudInfrastructure/Services/Email/CreationBody.cs b/AsbCloudInfrastructure/Services/Email/CreationBody.cs deleted file mode 100644 index 25405f55..00000000 --- a/AsbCloudInfrastructure/Services/Email/CreationBody.cs +++ /dev/null @@ -1,96 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace AsbCloudInfrastructure -{ - - abstract class BodyCreation - { - public int idWell { get; set; } - public int idDocument { get; set; } - public string mailSubject { get; set; } = "#fieldName, #clusterName, #wellName. Программа бурения. #action."; - public string wellName { get; set; } - public string clusterName { get; set; } - public string fieldName { get; set; } - public string documentCategory { get; set; } - public string documentName { get; set; } - public string coordinatingName { get; set; } - public string coordinatingComment { get; set; } - public string userName { get; set; } - public static string logo { get; } = "data:image/png;base64,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"; - public static string bodySign { get; } = $"



" + - $"{companyName}
Это письмо сформировано автоматически.
Для получения помощи по работе на портале " + - $"{webPlatform} обращайтесь по адресу {supportMail}
"; - public static string webPlatform { get; } = ""; - public static string companyName { get; } = "ООО \"НафтаГаз\""; - public static string supportMail { get; } = "support@autodrilling.ru"; - public abstract string GetBodyHTML(); - - } - - class MailUserPublisher : BodyCreation - { - public override string GetBodyHTML() - { - mailSubject = mailSubject.Replace("#fieldName", fieldName); - mailSubject = mailSubject.Replace("#clusterName", clusterName); - mailSubject = mailSubject.Replace("#wellName", fieldName); - mailSubject = mailSubject.Replace("#action", "Добавление публикатора"); - return $"
Здравствуйте, {userName}.

< font size = \"5\">На портале " + - $"{webPlatform} началось создание программы бурения скважины {wellName}, " + - $"куст {clusterName}, месторождение {fieldName}." + - $"

От вас ожидается загрузка на портал документа «{documentCategory}» в формате excel (*.xlsx)." + bodySign; - } - - - } - - class MailCoordinating : BodyCreation - { - public override string GetBodyHTML() - { - mailSubject = mailSubject.Replace("#fieldName", fieldName); - mailSubject = mailSubject.Replace("#clusterName", clusterName); - mailSubject = mailSubject.Replace("#wellName", fieldName); - mailSubject = mailSubject.Replace("#action", "Документ на согласование"); - return $"
Здравствуйте, {userName}.

На портал " + - $"{webPlatform} загружен документ " + - $" для согласования при создании программы бурения скважины , куст ({clusterName})" + - $", месторождение ({fieldName})." + bodySign; - } - } - - class PublisherRejected : BodyCreation - { - public override string GetBodyHTML() - { - mailSubject = mailSubject.Replace("#fieldName", fieldName); - mailSubject = mailSubject.Replace("#clusterName", clusterName); - mailSubject = mailSubject.Replace("#wellName", fieldName); - mailSubject = mailSubject.Replace("#action", "Документ отклонен"); - return $"
Здравствуйте, {userName}.

На портале " + - $"{webPlatform} отклонен загруженный вами документ
" + - $" по программе бурения скважины , куст " + - $"({clusterName}), месторождение ({fieldName}). Комментарий согласующего " + - $"({coordinatingName}):

{coordinatingComment}" + bodySign; - } - } - - class AllApprovals : BodyCreation - { - public override string GetBodyHTML() - { - mailSubject = mailSubject.Replace("#fieldName", fieldName); - mailSubject = mailSubject.Replace("#clusterName", clusterName); - mailSubject = mailSubject.Replace("#wellName", fieldName); - mailSubject = mailSubject.Replace("#action", "Все документы согласованы"); - return $"
Здравствуйте, {userName}.

На портале " + - $"{webPlatform} полностью согласован документ " + - $"
{documentName} " + - $"по программе бурения скважины , куст ({clusterName}), " + - $"месторождение ({fieldName}).
От вас ожидается загрузка на портал документа " + - $"«{documentCategory}» в формате excel (*.xlsx)." + bodySign; - } - } -} - diff --git a/AsbCloudInfrastructure/Services/Email/EmailService.cs b/AsbCloudInfrastructure/Services/Email/EmailService.cs index d71543bd..a969a943 100644 --- a/AsbCloudInfrastructure/Services/Email/EmailService.cs +++ b/AsbCloudInfrastructure/Services/Email/EmailService.cs @@ -34,6 +34,9 @@ namespace AsbCloudInfrastructure.Services this.backgroundWorker = backgroundWorker; } + public void EnqueueSend(string address, string subject, string htmlBody) + => new List { address }; + public void EnqueueSend(IEnumerable addresses, string subject, string htmlBody) { if (!IsConfigured) @@ -86,9 +89,7 @@ namespace AsbCloudInfrastructure.Services client.UseDefaultCredentials = false; client.Credentials = new System.Net.NetworkCredential(sender, smtpPassword); - // TODO: uncomment next when tested await client.SendMailAsync(message, token); - await Task.Delay(0); Trace.TraceInformation($"Send email to {string.Join(',', addresses)} subj:{subject} html body count {htmlBody.Count()}"); }; return func; diff --git a/AsbCloudInfrastructure/Services/Email/MailBodyFactory.cs b/AsbCloudInfrastructure/Services/Email/MailBodyFactory.cs new file mode 100644 index 00000000..66fa899d --- /dev/null +++ b/AsbCloudInfrastructure/Services/Email/MailBodyFactory.cs @@ -0,0 +1,122 @@ +using AsbCloudApp.Data; +using Microsoft.Extensions.Configuration; +using System; +using System.IO; + +namespace AsbCloudInfrastructure +{ + class MailBodyFactory + { + protected readonly string platformName; + private readonly string platformUrl; + protected readonly string companyName; + protected readonly string supportMail; + + public MailBodyFactory(IConfiguration configuration) + { + platformName = configuration.GetValue("email:platformName", "Цифровое бурение"); + platformUrl = configuration.GetValue("email:platformUrl", ""); + companyName = configuration.GetValue("email:companyName", "ООО \"Цифровое бурение\""); + supportMail = configuration.GetValue("email:supportMail", "support@digitaldrilling.ru"); + } + + public static string MakeSubject(WellDto well, string action) + { + var subj = $"{well.Deposit}, {well.Cluster}, {well.Caption}. Программа бурения. {action}"; + return subj; + } + + public string MakeMailBodyForNewPublisher(WellDto well, string userName, string documentCategory) + { + var drillingProgramHref = MakeDrillingProgramHref(well); + + var body = $"

Здравствуйте, {userName}.

" + + $"На портале {platformName} началось создание программы бурения скважины {drillingProgramHref}," + + $" куст {well.Cluster}, месторождение {well.Deposit}." + + $"

От вас ожидается загрузка на портал документа «{documentCategory}» в формате excel (*.xlsx)." + + MakeSignatue() + + $""; + return body; + } + + public string MakeMailBodyForApproverNewFile(WellDto well, string userName, int idFile, string fileName) + { + var fileDownloadHref = MakeFileDownloadHref(well.Id, idFile, fileName); + var drillingProgramHref = MakeDrillingProgramHref(well); + + var body = $"

Здравствуйте, {userName}.

" + + $"На портал {platformName} загружен документ {fileDownloadHref}" + + $" для согласования при создании программы бурения скважины {drillingProgramHref}, куст ({well.Cluster})" + + $", месторождение ({well.Deposit}).
" + + MakeSignatue() + + $""; + return body; + } + + public string MakeMailBodyForPublisherOnReject(WellDto well, string userName, int idFile, string fileName, FileMarkDto fileMark) + { + var fileDownloadHref = MakeFileDownloadHref(well.Id, idFile, fileName); + var drillingProgramHref = MakeDrillingProgramHref(well); + + var body = $"

Здравствуйте, {userName}.

" + + $"На портале {platformName} отклонен загруженный вами документ {fileDownloadHref} " + + $" по программе бурения скважины {drillingProgramHref}," + + $" куст {well.Cluster}, месторождение {well.Deposit}." + + $" Комментарий согласующего ({fileMark.User.Name} {fileMark.User.Surname}):
{fileMark.Comment}" + + MakeSignatue() + + $""; + return body; + } + + public string MakeMailBodyForPublisherOnFullAccept(WellDto well, string userName, int idFile, string fileName) + { + var fileDownloadHref = MakeFileDownloadHref(well.Id, idFile, fileName); + var drillingProgramHref = MakeDrillingProgramHref(well); + + var body = $"

Здравствуйте, {userName}.

" + + $"На портале {platformName} полностью согласован документ {fileDownloadHref} " + + $" по программе бурения скважины {drillingProgramHref}," + + $" куст {well.Cluster}, месторождение {well.Deposit}." + + MakeSignatue() + + $""; + return body; + } + + private string MakeFileDownloadHref(int idWell, int idFile, string fileName) + { + var fileDownloadUrl = $"{platformUrl}/api/well/{idWell}/files/{idFile}"; + var fileDownloadHref = MakeHref(fileDownloadUrl, fileName); + return fileDownloadHref; + } + + private string MakeDrillingProgramHref(WellDto well) + { + var drillingProgramUrl = $"{platformUrl}/api/well/{well.Id}/drillingProgram"; + var drillingProgramHref = MakeHref(drillingProgramUrl, well.Caption); + return drillingProgramHref; + } + + private static string MakeHref(string url, string text) + => $"{text}"; + + protected string MakeSignatue() + { + var logo = GetImageBase64("logo_32.png"); + var sign = $"
---
" + + $"{companyName}
Это письмо сформировано автоматически.
Для получения помощи по работе на портале " + + $"{platformName} обращайтесь по адресу {supportMail}"; + return sign; + } + + public static string GetImageBase64(string resourceFileName) + { + if (string.IsNullOrEmpty(resourceFileName)) + return null; + + var format = Path.GetExtension(resourceFileName).Trim('.'); + var logoFilePath = Path.Combine("Res" + resourceFileName); + var imageBytes = File.ReadAllBytes(logoFilePath); + return "data:image/" + format + ";base64," + Convert.ToBase64String(imageBytes); + } + } +}