using AsbCloudApp.Data; 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; public WellFinalDocumentsService(IAsbCloudDbContext context, IFileService fileService, IUserService userService, IWellService wellService, IConfiguration configuration, IEmailService emailService) : base(context) { this.context = context; this.fileService = fileService; this.userService = userService; this.wellService = wellService; this.configuration = configuration; this.emailService = emailService; } public async Task InsertRangeAsync(List dtos, CancellationToken token) { var data = await base.InsertRangeAsync(dtos, token); if (data > 0) { // Текст сообщения var message = "От Вас ожидается загрузка на портал документа «{0}»"; await GenerateMessage(dtos, message, token); } return data; } public async Task DeleteAsync(int dtoId, CancellationToken token) { // Получение данные удаляемой записи var dtos = await context.WellFinalDocuments.Where(x => x.Id == dtoId) .Select(x => new WellFinalDocumentsDBDto { IdCategory = x.IdCategory, IdWell = x.IdWell, IdUser = x.IdUser, IdFile = x.IdFile }) .ToListAsync(token) .ConfigureAwait(false); var data = await base.DeleteAsync(dtoId, token); if (data > 0) { // Текст сообщения var message = "Вас удалили из ответственных за загрузку документа «{0}»"; await GenerateMessage(dtos, message, token); } return data; } public async Task> GetByWellId(int idWell, CancellationToken token) { var result = new List(); // Выбиираем все дела, по id скважины 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, ListResponsible = allUsers.Where(x => userIds.Contains(x.Id)), CountFiles = fileIds.Count(x => x.HasValue), File = actualFile }); }); } return result; } public async Task> GetListResponsiblesAsync(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, Stream fileStream, string fileName, CancellationToken token) { // Получаем запись var dtos = await context.WellFinalDocuments.Where(x => x.Id == idDto) .Select(x => new WellFinalDocumentsDBDto { Id = x.Id, IdCategory = x.IdCategory, IdWell = x.IdWell, IdUser = x.IdUser, IdFile = x.IdFile }) .ToListAsync(token) .ConfigureAwait(false); var dto = dtos.FirstOrDefault(); // Сохраняем файл и добавляем id файла в запись var file = await fileService.SaveAsync(dto.IdWell, dto.IdUser, dto.IdCategory, fileName, fileStream, token).ConfigureAwait(false); if (file != null) dto.IdFile = file.Id; var data = await base.UpdateAsync(dto, token); return data; } public async Task GetHistoryFileByIdCategory(int idWell, int idCategory, CancellationToken token) { // Выбиираем все id файлов, по id скважины и id категории 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 GenerateMessage(List dtos, string message, CancellationToken token) { // Получам пользователей var userIds = dtos.Select(x => x.IdUser); var allUsers = await userService.GetAllAsync(token) .ConfigureAwait(false); var users = allUsers.Where(x => userIds.Contains(x.Id)); // Получаем категории файлов var categoryIds = dtos.Select(x => x.IdCategory); var category = await context.FileCategories .Where(x => categoryIds.Contains(x.Id)) .ToListAsync(token) .ConfigureAwait(false); foreach (var item in dtos) { var currentUser = users.FirstOrDefault(x => x.Id == item.IdUser); var categoryName = category.FirstOrDefault(x => x.Id == item.IdCategory)?.Name; await SendMessage(item.IdWell, currentUser, categoryName, message, token); } } private async Task SendMessage(int idWell, UserDto user, string documentCategory, string message, CancellationToken token) { var well = await wellService.GetOrDefaultAsync(idWell, token); var factory = new MailBodyFactory(configuration); var subject = MailBodyFactory.MakeSubject(well, string.Format(message, documentCategory)); var body = factory.MakeMailBodyForNewPublisher(well, user.Name, 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 }; } }