using AsbCloudApp.Data; using AsbCloudApp.Exceptions; using AsbCloudApp.Services; using AsbCloudDb.Model; using AsbCloudInfrastructure.Repository; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace AsbCloudInfrastructure.Services { /// /// Сервис "Дело скважины" /// public class WellFinalDocumentsService : CrudServiceBase, IWellFinalDocumentsService { private readonly IAsbCloudDbContext context; private readonly IFileService fileService; private readonly IUserService userService; private readonly IWellService wellService; private readonly IConfiguration configuration; private readonly IEmailService emailService; private readonly IFileCategoryService fileCategoryService; private const int ResultSaveCategoryFile = 0; public WellFinalDocumentsService(IAsbCloudDbContext context, IFileService fileService, IUserService userService, IWellService wellService, IConfiguration configuration, IEmailService emailService, IFileCategoryService fileCategoryService) : base(context) { this.context = context; this.fileService = fileService; this.userService = userService; this.wellService = wellService; this.configuration = configuration; this.emailService = emailService; this.fileCategoryService = fileCategoryService; } public override async Task InsertRangeAsync(IEnumerable dtos, CancellationToken token) { var data = await base.InsertRangeAsync(dtos, token); if (data > 0) { var message = "от Вас ожидается загрузка на портал документа «{0}»"; await GenerateMessageAsync(dtos, message, token); } return data; } public override async Task DeleteAsync(int dtoId, CancellationToken token) { var entity = await context.WellFinalDocuments .AsNoTracking() .FirstOrDefaultAsync(x => x.Id == dtoId); var dto = Convert(entity); var data = await base.DeleteAsync(dtoId, token); if (data > 0) { var message = "Вас удалили из ответственных за загрузку документа «{0}»"; await GenerateMessageAsync(new List { dto }, message, token); } return data; } public async Task> GetByWellId(int idWell, CancellationToken token) { var result = new List(); var wells = await context.WellFinalDocuments.Where(x => x.IdWell == idWell) .ToListAsync(token) .ConfigureAwait(false); if (wells.Any()) { var category = await context.FileCategories .Where(x => wells.Select(w => w.IdCategory).Contains(x.Id)) .ToListAsync(token) .ConfigureAwait(false); var wellFinalDocs = category .GroupJoin(wells, fc => fc.Id, w => w.IdCategory, (o, i) => new { NameCategory = o.Name, Wells = i }) .ToList(); wellFinalDocs.ForEach(async item => { var userIds = item.Wells .Select(x => x.IdUser) .ToList(); var allUsers = await userService.GetAllAsync(token) .ConfigureAwait(false); var fileIds = item.Wells .Where(x => x.IdFile != null) .Select(x => x.IdFile) .OrderByDescending(x => x) .ToList(); FileInfoDto actualFile = null; if (fileIds.Any()) { var actualFileId = fileIds.FirstOrDefault(); actualFile = fileService.GetInfoAsync(actualFileId ?? default(int), token).Result; } result.Add(new WellFinalDocumentsDto { IdWell = idWell, NameCategory = item.NameCategory, Publishers = allUsers.Where(x => userIds.Contains(x.Id)), FilesCount = fileIds.Count(x => x.HasValue), File = actualFile }); }); } return result; } public async Task> GetPublishersAsync(int idWell, CancellationToken token) { var companyIds = await context.RelationCompaniesWells .Where(x => x.IdWell == idWell).Select(x => x.IdCompany) .ToListAsync(token) .ConfigureAwait(false); var allUsers = await userService.GetAllAsync(token) .ConfigureAwait(false); return allUsers.Where(x => { var idCompany = x.IdCompany ?? default(int); return companyIds.Contains(idCompany); }) .OrderBy(x => x.Surname) .ToList(); } public async Task SaveCategoryFile(int idDto, int idUser, Stream fileStream, string fileName, CancellationToken token) { var entity = await context.WellFinalDocuments .AsNoTracking() .FirstOrDefaultAsync(x => x.Id == idDto); if (entity.IdUser != idUser) throw new ArgumentInvalidException("Пользователь не является ответственным за загрузку файла для данной категории."); var dto = Convert(entity); var file = await fileService.SaveAsync(dto.IdWell, dto.IdUser, dto.IdCategory, fileName, fileStream, token).ConfigureAwait(false); if (file is not null) { dto.IdFile = file.Id; return await base.UpdateAsync(dto, token); } else return ResultSaveCategoryFile; } public async Task GetFilesHistoryByIdCategory(int idWell, int idCategory, CancellationToken token) { var wellsIds = await context.WellFinalDocuments .Where(x => idWell == x.IdWell && x.IdCategory == idCategory && x.IdFile != null) .Select(x => (int)x.IdFile) .ToListAsync(token) .ConfigureAwait(false); var files = await fileService.GetInfoByIdsAsync(wellsIds, token).ConfigureAwait(false); return new WellFinalDocumentsHistoryDto { IdWell = idWell, IdCategory = idCategory, File = files }; } private async Task GenerateMessageAsync(IEnumerable dtos, string message, CancellationToken token) { foreach (var item in dtos) { var user = await userService.GetOrDefaultAsync(item.IdUser, token); var category = await fileCategoryService.GetOrDefaultAsync(item.IdCategory, token); var well = await wellService.GetOrDefaultAsync(item.IdWell, token); SendMessage(well, user, category.Name, message, token); } } private void SendMessage(WellDto well, UserDto user, string documentCategory, string message, CancellationToken token) { var factory = new WellFinalDocumentMailBodyFactory(configuration); var subject = factory.MakeSubject(well, documentCategory); var body = factory.MakeMailBodyForWellFinalDocument(well, user.Name ?? user.Surname, string.Format(message, documentCategory)); emailService.EnqueueSend(user.Email, subject, body); } private static WellFinalDocumentsDBDto Convert(WellFinalDocuments dto) => new WellFinalDocumentsDBDto { Id = dto.Id, IdCategory = dto.IdCategory, IdWell = dto.IdWell, IdUser = dto.IdUser, IdFile = dto.IdFile }; } }