From 42778501560aae1052f0aff7e236718ee0651674 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Wed, 23 Nov 2022 14:03:08 +0500 Subject: [PATCH 1/3] #7912198 implement ReNotifyPublishers --- .../Services/IWellFinalDocumentsService.cs | 20 ++++++--- .../Services/WellFinalDocumentsService.cs | 44 +++++++++++++++++-- .../WellFinalDocumentsController.cs | 32 +++++++++++--- 3 files changed, 81 insertions(+), 15 deletions(-) diff --git a/AsbCloudApp/Services/IWellFinalDocumentsService.cs b/AsbCloudApp/Services/IWellFinalDocumentsService.cs index 4da098ce..30459a43 100644 --- a/AsbCloudApp/Services/IWellFinalDocumentsService.cs +++ b/AsbCloudApp/Services/IWellFinalDocumentsService.cs @@ -25,10 +25,10 @@ namespace AsbCloudApp.Services /// Получение всех записей /// /// - /// + /// запрашивающий пользователь, для проверки его прав и текста сообщения /// /// - Task GetByWellId(int idWell, int idUser, CancellationToken token); + Task GetByWellIdAsync(int idWell, int idUser, CancellationToken token); /// /// Получение списка ответственных @@ -45,19 +45,29 @@ namespace AsbCloudApp.Services /// /// /// - Task GetFilesHistoryByIdCategory(int idWell, int idCategory, CancellationToken token); + Task GetFilesHistoryByIdCategoryAsync(int idWell, int idCategory, CancellationToken token); /// /// Сохранение файла /// /// /// - /// + /// пользователь, который сохраняет файл /// /// /// /// - Task SaveCategoryFile(int idWell, int idCategory, int idUser, Stream fileStream, string fileName, CancellationToken token); + Task SaveCategoryFileAsync(int idWell, int idCategory, int idUser, Stream fileStream, string fileName, CancellationToken token); + + /// + /// Повторно оповестить ответственных за загрузку + /// + /// + /// запрашивающий пользователь, для проверки его прав и текста сообщения + /// + /// + /// count of notified publishers + Task ReNotifyPublishersAsync(int idWell, int idUser, int idCategory, CancellationToken token); } #nullable disable } \ No newline at end of file diff --git a/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs b/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs index ec417604..c0d352cc 100644 --- a/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs +++ b/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs @@ -4,7 +4,6 @@ using AsbCloudApp.Repositories; using AsbCloudApp.Requests; using AsbCloudApp.Services; using AsbCloudDb.Model; -using AsbCloudInfrastructure.Repository; using Mapster; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; @@ -50,6 +49,7 @@ namespace AsbCloudInfrastructure.Services this.fileCategoryService = fileCategoryService; } + /// public async Task UpdateRangeAsync(int idWell, IEnumerable? dtos, CancellationToken token) { if (dtos is not null) @@ -81,7 +81,8 @@ namespace AsbCloudInfrastructure.Services throw new ArgumentInvalidException("Данные по категориям отсутствуют."); } - public async Task GetByWellId(int idWell, int idUser, CancellationToken token) + /// + public async Task GetByWellIdAsync(int idWell, int idUser, CancellationToken token) { var entities = await context.WellFinalDocuments .Include(d => d.Category) @@ -127,6 +128,7 @@ namespace AsbCloudInfrastructure.Services return result; } + /// public async Task> GetAvailableUsersAsync(int idWell, CancellationToken token) { var companyIds = await context.RelationCompaniesWells @@ -145,7 +147,8 @@ namespace AsbCloudInfrastructure.Services .ToArray(); } - public async Task SaveCategoryFile(int idWell, int idCategory, int idUser, Stream fileStream, string fileName, CancellationToken token) + /// + public async Task SaveCategoryFileAsync(int idWell, int idCategory, int idUser, Stream fileStream, string fileName, CancellationToken token) { var entity = await context.WellFinalDocuments .AsNoTracking() @@ -162,7 +165,8 @@ namespace AsbCloudInfrastructure.Services return file?.Id ?? FileServiceThrewException; //TODO: изменить когда файловый сервис будет переведен на nullable } - public async Task GetFilesHistoryByIdCategory(int idWell, int idCategory, CancellationToken token) + /// + public async Task GetFilesHistoryByIdCategoryAsync(int idWell, int idCategory, CancellationToken token) { var request = new FileRequest { @@ -178,6 +182,37 @@ namespace AsbCloudInfrastructure.Services }; } + /// + public async Task ReNotifyPublishersAsync(int idWell, int idUser, int idCategory, CancellationToken token) + { + WellCaseDto wellCase = await GetByWellIdAsync(idWell, idUser, token); + + if (wellCase.PermissionToSetPubliher) + throw new ForbidException("Повторная отправка оповещений Вам не разрешена"); + + var requester = userRepository.GetOrDefault(idUser); + if (requester is null) + throw new ForbidException("Не удается вас опознать"); + + var docs = wellCase.WellFinalDocuments + .Where(doc => doc.IdCategory == idCategory) + .Where(doc => doc.File is null) + .SelectMany(doc => doc.Publishers + .Select(pub => new WellFinalDocumentDBDto { + IdCategory = idCategory, + IdUser = pub.Id, + IdWell = idWell + })); + + if(!docs.Any()) + throw new Exception("Нет такой категории, или в нее уже загружен документ"); + + var message = requester.MakeDisplayName() + " ожидает от Вас загрузку на портал документа «{{0}}»"; + await GenerateMessageAsync(docs, message, token); + + return docs.Count(); + } + private async Task GenerateMessageAsync(IEnumerable dtos, string message, CancellationToken token) { foreach (var item in dtos) @@ -203,6 +238,7 @@ namespace AsbCloudInfrastructure.Services private static WellFinalDocumentDBDto Convert(WellFinalDocument entity) => entity.Adapt(); + } #nullable disable } diff --git a/AsbCloudWebApi/Controllers/WellFinalDocumentsController.cs b/AsbCloudWebApi/Controllers/WellFinalDocumentsController.cs index 12be0baf..0e599da9 100644 --- a/AsbCloudWebApi/Controllers/WellFinalDocumentsController.cs +++ b/AsbCloudWebApi/Controllers/WellFinalDocumentsController.cs @@ -47,7 +47,7 @@ namespace AsbCloudWebApi.Controllers return Forbid(); var idUser = User?.GetUserId(); - var data = await this.wellFinalDocumentsService.GetByWellId(idWell, idUser ?? default, token); + var data = await this.wellFinalDocumentsService.GetByWellIdAsync(idWell, idUser ?? default, token); return Ok(data); } @@ -84,7 +84,27 @@ namespace AsbCloudWebApi.Controllers if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) return Forbid(); - var data = await this.wellFinalDocumentsService.UpdateRangeAsync(idWell, dtos, token); + var data = await wellFinalDocumentsService.UpdateRangeAsync(idWell, dtos, token); + return Ok(data); + } + + /// + /// Повторно оповестить ответственных за загрузку + /// + /// + /// + /// + /// количество оповещенных публикаторов + [HttpPut("{idWell}")] + [Permission("WellFinalDocuments.editPublisher")] + [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] + public async Task ReNotifyPublishersAsync(int idWell, [Required] int idCategory, CancellationToken token = default) + { + if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) + return Forbid(); + + var idUser = User.GetUserId() ?? -1; + var data = await wellFinalDocumentsService.ReNotifyPublishersAsync(idWell, idUser, idCategory, token); return Ok(data); } @@ -98,14 +118,14 @@ namespace AsbCloudWebApi.Controllers [HttpGet("{idWell}/history")] [Permission] [ProducesResponseType(typeof(WellFinalDocumentsHistoryDto), (int)System.Net.HttpStatusCode.OK)] - public async Task GetFilesHistoryByIdCategory(int idWell, + public async Task GetFilesHistoryByIdCategoryAsync(int idWell, [Required] int idCategory, CancellationToken token = default) { if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) return Forbid(); - var data = await this.wellFinalDocumentsService.GetFilesHistoryByIdCategory(idWell, idCategory, token); + var data = await this.wellFinalDocumentsService.GetFilesHistoryByIdCategoryAsync(idWell, idCategory, token); return Ok(data); } @@ -120,14 +140,14 @@ namespace AsbCloudWebApi.Controllers [HttpPost("{idWell}")] [Permission] [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task SaveCategoryFile(int idWell, [Required] int idCategory, [Required] IFormFile file, CancellationToken token = default) + public async Task SaveCategoryFileAsync(int idWell, [Required] int idCategory, [Required] IFormFile file, CancellationToken token = default) { if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) return Forbid(); var idUser = User.GetUserId() ?? -1; var fileStream = file.OpenReadStream(); - var data = await this.wellFinalDocumentsService.SaveCategoryFile(idWell, idCategory, idUser, fileStream, file.FileName, token); + var data = await this.wellFinalDocumentsService.SaveCategoryFileAsync(idWell, idCategory, idUser, fileStream, file.FileName, token); return Ok(data); } From f88307f7b98c5c1984a6128489f1cbac09b9d3e0 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Wed, 23 Nov 2022 17:21:47 +0500 Subject: [PATCH 2/3] #7912198 rename methods in tests --- .../ServicesTests/WellFinalDocumentsServiceTest.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/AsbCloudWebApi.Tests/ServicesTests/WellFinalDocumentsServiceTest.cs b/AsbCloudWebApi.Tests/ServicesTests/WellFinalDocumentsServiceTest.cs index d65e29c7..25cf1d42 100644 --- a/AsbCloudWebApi.Tests/ServicesTests/WellFinalDocumentsServiceTest.cs +++ b/AsbCloudWebApi.Tests/ServicesTests/WellFinalDocumentsServiceTest.cs @@ -72,7 +72,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests [Fact] public async Task GetWellFinalDocument_return_collection_rows() { - var data = await service.GetByWellId(90, 1,CancellationToken.None); + var data = await service.GetByWellIdAsync(90, 1,CancellationToken.None); Assert.NotNull(data); } @@ -86,7 +86,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests [Fact] public async Task GetHistoryFileByIdCategory_return_data_hitory() { - var data = await service.GetFilesHistoryByIdCategory(90, 10018, CancellationToken.None); + var data = await service.GetFilesHistoryByIdCategoryAsync(90, 10018, CancellationToken.None); Assert.NotNull(data); } @@ -94,7 +94,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests public async Task SaveCategoryFile_return_id_edit_record() { var stream = new FileStream("D:\\test\\test.txt", FileMode.Open); - var data = await service.SaveCategoryFile(21, 10018, 78, stream, "test.txt", CancellationToken.None); + var data = await service.SaveCategoryFileAsync(21, 10018, 78, stream, "test.txt", CancellationToken.None); Assert.Equal(21, data); } } From 8209b61bad09afd1e77e5c5ef1917f77b4b49545 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Fri, 25 Nov 2022 09:34:20 +0500 Subject: [PATCH 3/3] #7912198 Tests ok --- .../Data/WellFinalDocumentsHistoryDto.cs | 2 +- .../Model/DefaultData/DefaultContextData.cs | 40 ++++ AsbCloudDb/Model/DefaultData/DefaultData.cs | 39 ---- AsbCloudDb/Model/DefaultData/EntityFiller.cs | 2 +- AsbCloudDb/Model/DefaultData/IEntityFiller.cs | 2 +- AsbCloudDb/Readme.md | 2 - .../Services/Email/BaseFactory.cs | 3 +- .../Services/WellFinalDocumentsService.cs | 15 +- .../WellFinalDocumentsServiceTest.cs | 201 +++++++++++++++--- 9 files changed, 224 insertions(+), 82 deletions(-) create mode 100644 AsbCloudDb/Model/DefaultData/DefaultContextData.cs delete mode 100644 AsbCloudDb/Model/DefaultData/DefaultData.cs diff --git a/AsbCloudApp/Data/WellFinalDocumentsHistoryDto.cs b/AsbCloudApp/Data/WellFinalDocumentsHistoryDto.cs index ec57a5de..f7887b25 100644 --- a/AsbCloudApp/Data/WellFinalDocumentsHistoryDto.cs +++ b/AsbCloudApp/Data/WellFinalDocumentsHistoryDto.cs @@ -21,7 +21,7 @@ namespace AsbCloudApp.Data /// /// Файлы /// - public IEnumerable? File { get; set; } + public IEnumerable Files { get; set; } = null!; } #nullable disable } diff --git a/AsbCloudDb/Model/DefaultData/DefaultContextData.cs b/AsbCloudDb/Model/DefaultData/DefaultContextData.cs new file mode 100644 index 00000000..bc664a78 --- /dev/null +++ b/AsbCloudDb/Model/DefaultData/DefaultContextData.cs @@ -0,0 +1,40 @@ +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; + +namespace AsbCloudDb.Model.DefaultData +{ + public static class DefaultContextData + { + public static Dictionary GetFillers() + { + var fillers = new Dictionary + { + // Order does meter + { typeof(UserRole), new EntityFillerUserRole() }, + { typeof(RelationUserRoleUserRole), new EntityFillerRelationUserRoleUserRole()}, + { typeof(Permission), new EntityFillerPermission()}, + { typeof(RelationUserRolePermission), new EntityFillerRelationUserRolePermission()}, + { typeof(User), new EntityFillerUser()}, + { typeof(RelationUserUserRole), new EntityFillerRelationUserUserRole()}, + { typeof(Company), new EntityFillerCompany()}, + { typeof(WellOperationCategory), new EntityFillerWellOperationCategory()}, + { typeof(FileCategory), new EntityFillerFileCategory()}, + { typeof(WellSectionType), new EntityFillerWellSectionType()}, + { typeof(WellType), new EntityFillerWellType()}, + { typeof(MeasureCategory), new EntityFillerMeasureCategory()}, + { typeof(CompanyType), new EntityFillerCompanyType()}, + { typeof(AsbCloudDb.Model.Subsystems.Subsystem), new EntityFillerSubsystem() }, + }; + return fillers; + } + + public static void Fill(ModelBuilder modelBuilder) + { + var fillers = GetFillers(); + + foreach (var filler in fillers.Values) + filler.FillData(modelBuilder); + } + } +} diff --git a/AsbCloudDb/Model/DefaultData/DefaultData.cs b/AsbCloudDb/Model/DefaultData/DefaultData.cs deleted file mode 100644 index 770cfbb3..00000000 --- a/AsbCloudDb/Model/DefaultData/DefaultData.cs +++ /dev/null @@ -1,39 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using System.Collections.Generic; - -namespace AsbCloudDb.Model.DefaultData -{ - internal static class DefaultContextData - { - public static IEnumerable GetFillers() - { - var fillers = new IEntityFiller[] - { - // Order does meter - new EntityFillerUserRole(), - new EntityFillerRelationUserRoleUserRole(), - new EntityFillerPermission(), - new EntityFillerRelationUserRolePermission(), - new EntityFillerUser(), - new EntityFillerRelationUserUserRole(), - new EntityFillerCompany(), - new EntityFillerWellOperationCategory(), - new EntityFillerFileCategory(), - new EntityFillerWellSectionType(), - new EntityFillerWellType(), - new EntityFillerMeasureCategory(), - new EntityFillerCompanyType(), - new EntityFillerSubsystem(), - }; - return fillers; - } - - public static void Fill(ModelBuilder modelBuilder) - { - var fillers = GetFillers(); - - foreach (var filler in fillers) - filler.FillData(modelBuilder); - } - } -} diff --git a/AsbCloudDb/Model/DefaultData/EntityFiller.cs b/AsbCloudDb/Model/DefaultData/EntityFiller.cs index 3b401963..f6f5f016 100644 --- a/AsbCloudDb/Model/DefaultData/EntityFiller.cs +++ b/AsbCloudDb/Model/DefaultData/EntityFiller.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; namespace AsbCloudDb.Model.DefaultData { - internal abstract class EntityFiller : IEntityFiller + public abstract class EntityFiller : IEntityFiller where TEntity : class { public abstract TEntity[] GetData(); diff --git a/AsbCloudDb/Model/DefaultData/IEntityFiller.cs b/AsbCloudDb/Model/DefaultData/IEntityFiller.cs index 0734e998..d505790f 100644 --- a/AsbCloudDb/Model/DefaultData/IEntityFiller.cs +++ b/AsbCloudDb/Model/DefaultData/IEntityFiller.cs @@ -2,7 +2,7 @@ namespace AsbCloudDb.Model.DefaultData { - internal interface IEntityFiller + public interface IEntityFiller { void FillData(ModelBuilder modelBuilder); } diff --git a/AsbCloudDb/Readme.md b/AsbCloudDb/Readme.md index fc81d0b9..8d74cf4c 100644 --- a/AsbCloudDb/Readme.md +++ b/AsbCloudDb/Readme.md @@ -54,8 +54,6 @@ SELECT timescaledb_pre_restore(); ### Step 3. Restore DB, then [Longest operation] Terminal: ``` -sudo -u postgres psql -p 5499 -U postgres postgres -W < dump_2021-11-26.bak -or sudo -u postgres pg_restore -Fc -d postgres dump_2021-11-26.bak ``` OR psql: diff --git a/AsbCloudInfrastructure/Services/Email/BaseFactory.cs b/AsbCloudInfrastructure/Services/Email/BaseFactory.cs index 1e94cab3..81a319cd 100644 --- a/AsbCloudInfrastructure/Services/Email/BaseFactory.cs +++ b/AsbCloudInfrastructure/Services/Email/BaseFactory.cs @@ -29,7 +29,8 @@ namespace AsbCloudInfrastructure.Services.Email var resoursesDir = "Res"; var logoFilePath = Path.Combine(baseDir, resoursesDir, resourceFileName); - + if(!File.Exists(logoFilePath)) + return string.Empty; var imageBytes = File.ReadAllBytes(logoFilePath); var format = Path.GetExtension(resourceFileName).Trim('.'); return "data:image/" + format + ";base64," + Convert.ToBase64String(imageBytes); diff --git a/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs b/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs index c0d352cc..818eef38 100644 --- a/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs +++ b/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs @@ -136,14 +136,13 @@ namespace AsbCloudInfrastructure.Services .ToListAsync(token) .ConfigureAwait(false); - var allUsers = await userRepository.GetAllAsync(token) + var allUsers = await userRepository + .GetAllAsync(token) .ConfigureAwait(false); - return allUsers.Where(x => { - var idCompany = x.IdCompany ?? default(int); - return companyIds.Contains(idCompany); - }) + return allUsers.Where(x => x.IdCompany is not null && companyIds.Contains(x.IdCompany ?? int.MinValue)) .OrderBy(x => x.Surname) + .Select(u => u as UserDto) .ToArray(); } @@ -178,7 +177,7 @@ namespace AsbCloudInfrastructure.Services return new WellFinalDocumentsHistoryDto { IdWell = idWell, IdCategory = idCategory, - File = files + Files = files }; } @@ -187,10 +186,10 @@ namespace AsbCloudInfrastructure.Services { WellCaseDto wellCase = await GetByWellIdAsync(idWell, idUser, token); - if (wellCase.PermissionToSetPubliher) + if (!wellCase.PermissionToSetPubliher) throw new ForbidException("Повторная отправка оповещений Вам не разрешена"); - var requester = userRepository.GetOrDefault(idUser); + var requester = await userRepository.GetOrDefaultAsync(idUser, token); if (requester is null) throw new ForbidException("Не удается вас опознать"); diff --git a/AsbCloudWebApi.Tests/ServicesTests/WellFinalDocumentsServiceTest.cs b/AsbCloudWebApi.Tests/ServicesTests/WellFinalDocumentsServiceTest.cs index 25cf1d42..caa5c3ed 100644 --- a/AsbCloudWebApi.Tests/ServicesTests/WellFinalDocumentsServiceTest.cs +++ b/AsbCloudWebApi.Tests/ServicesTests/WellFinalDocumentsServiceTest.cs @@ -2,100 +2,243 @@ using AsbCloudApp.Services; using AsbCloudDb.Model; using AsbCloudInfrastructure.Services; -using Microsoft.Extensions.Configuration; using Moq; using System.Threading; using System.Threading.Tasks; using Xunit; using System.IO; -using System.Collections.Generic; using System.Linq; using AsbCloudApp.Repositories; -using AsbCloudInfrastructure.Repository; +using AsbCloudApp.Exceptions; namespace AsbCloudWebApi.Tests.ServicesTests { public class WellFinalDocumentsServiceTest { - private readonly AsbCloudDbContext context; - private WellFinalDocumentsService service; - private readonly Mock fileServiceMock; + private const int validInsertedFileId = 555; + private const int idWellFinalDocCategory = 10_000; + private const string editPublisherPermission = "WellFinalDocuments.editPublisher"; + private readonly WellFinalDocumentsService service; private readonly Mock userRepositoryMock; private readonly Mock wellServiceMock; - private readonly Mock configurationMock; private readonly Mock emailServiceMock; private readonly Mock fileCategoryService; - private readonly IEnumerable users = new List { - new UserDto { + private static readonly UserExtendedDto[] users = new []{ + new UserExtendedDto { Id = 1, IdCompany = 1, - Name = "test", + Surname = "Tester 1", + Name = "Peppa", Email = "test@test.com" }, - new UserDto { + new UserExtendedDto { Id = 3, IdCompany = 1, - Name = "test1", + Surname = "Tester 3", + Name = "Jourge", Email = "test1@test1.com" } }; + + private static readonly WellFinalDocument[] wellFinalDocuments = new[] + { + new WellFinalDocument { + IdCategory = idWellFinalDocCategory, + IdUser = users[0].Id, + User = new User{ + Id = users[0].Id, + Surname = users[0].Surname, + Email = users[0].Email, + }, + IdWell = 1, + Category = new (){ Id = idWellFinalDocCategory, Name = "Проект на бурение транспортного и горизонтального участков скважины"}, + }, + }; + + private static readonly RelationCompanyWell[] relationCompanyWell = new[] + { + new RelationCompanyWell {IdWell = 1, IdCompany= 1} + }; + private readonly Mock fileRepositoryMock; + private readonly Mock fileStorageRepositoryMock; + private readonly FileService fileService; + private readonly Mock contextMock; public WellFinalDocumentsServiceTest() { - context = TestHelpter.MakeRealTestContext(); - context.SaveChanges(); + contextMock = new Mock(); + contextMock.AddDbSetMock(users); + contextMock.AddDbSetMock(wellFinalDocuments); + contextMock.AddDbSetMock(relationCompanyWell); + + fileRepositoryMock = new Mock(); + fileRepositoryMock.Setup(r => r.InsertAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync(validInsertedFileId); + fileRepositoryMock.Setup(r => r.GetOrDefaultAsync(validInsertedFileId, It.IsAny())) + .ReturnsAsync(new FileInfoDto {Id = validInsertedFileId}); + + fileStorageRepositoryMock = new Mock(); + fileService = new FileService(fileRepositoryMock.Object, fileStorageRepositoryMock.Object); - fileServiceMock = new Mock(); userRepositoryMock = new Mock(); - userRepositoryMock.Setup(x => x.GetAllAsync(CancellationToken.None)).Returns(Task.Run(() => users.Select(x => (UserExtendedDto)x))); + userRepositoryMock.Setup(x => x.GetAllAsync(It.IsAny())) + .ReturnsAsync(users); + userRepositoryMock.Setup(x => x.GetOrDefault(It.IsAny())) + .Returns(id => GetOrDefaultUserById(id)); + + userRepositoryMock.Setup(x => x.GetOrDefaultAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync((int id, CancellationToken token) => GetOrDefaultUserById(id)); + + UserExtendedDto? GetOrDefaultUserById(int id) + => users + .Where(u => u.Id == id) + .Select(u => new UserExtendedDto { + Id = u.Id, + IdCompany = u.IdCompany, + Email = u.Email, + Name = u.Name, + Patronymic = u.Patronymic, + Surname = u.Surname, + IdState = u.IdState, + Login = u.Login, + Position = u.Position + }) + .FirstOrDefault(); + + userRepositoryMock.Setup(x => x.HasPermission(users[0].Id, editPublisherPermission)) + .Returns(true); wellServiceMock = new Mock(); - configurationMock = new Mock(); + wellServiceMock.Setup(s => s.GetOrDefaultAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync((int id, CancellationToken _) => new WellDto { + Id = id, + Caption = "well 1", + Cluster = "cluster 1", + Deposit = "deposit 1" }); + var configuration = new Microsoft.Extensions.Configuration.ConfigurationBuilder().Build(); + emailServiceMock = new Mock(); fileCategoryService = new Mock(); + fileCategoryService.Setup(s => s.GetOrDefaultAsync(idWellFinalDocCategory, It.IsAny())) + .ReturnsAsync((int id, CancellationToken _) => new FileCategoryDto + { + Id = idWellFinalDocCategory, + Name = "Проект на бурение транспортного и горизонтального участков скважины" + }); service = new WellFinalDocumentsService( - context: context, - fileService: fileServiceMock.Object, + context: contextMock.Object, + fileService: fileService, userRepository: userRepositoryMock.Object, wellService: wellServiceMock.Object, - configuration: configurationMock.Object, + configuration: configuration, emailService: emailServiceMock.Object, fileCategoryService: fileCategoryService.Object); } - ~WellFinalDocumentsServiceTest() + [Fact] + public async Task UpdateRangeAsync_sends_mail() { + WellFinalDocumentInputDto[] docs = { + new (){ + IdCategory = idWellFinalDocCategory, + IdsPublishers = new int[]{ users[0].Id } + }}; + + contextMock.Invocations.Clear(); + contextMock.Setup(c => c.SaveChanges()) + .Returns(1); + contextMock.Setup(c => c.SaveChangesAsync(It.IsAny())) + .ReturnsAsync(1); + + var count = await service.UpdateRangeAsync(1, docs, CancellationToken.None); + Assert.Equal(1, count); + emailServiceMock.Verify(s => s.EnqueueSend(It.IsAny(), It.IsAny(), It.IsAny())); } [Fact] - public async Task GetWellFinalDocument_return_collection_rows() + public async Task GetByWellIdAsync_return_empty_case() { var data = await service.GetByWellIdAsync(90, 1,CancellationToken.None); Assert.NotNull(data); + Assert.Empty(data.WellFinalDocuments); } [Fact] - public async Task GetListResponsibles_return_cnt_users() + public async Task GetByWellIdAsync_return_one_document() + { + var data = await service.GetByWellIdAsync(1, 1, CancellationToken.None); + Assert.NotNull(data); + Assert.Single(data.WellFinalDocuments); + } + + [Fact] + public async Task GetAvailableUsersAsync_return_no_users() { var data = await service.GetAvailableUsersAsync(90, CancellationToken.None); Assert.NotNull(data); + Assert.Empty(data); } [Fact] - public async Task GetHistoryFileByIdCategory_return_data_hitory() + public async Task GetAvailableUsersAsync_return_two_users() { - var data = await service.GetFilesHistoryByIdCategoryAsync(90, 10018, CancellationToken.None); + var data = await service.GetAvailableUsersAsync(1, CancellationToken.None); Assert.NotNull(data); + Assert.Equal(2, data.Count()); } [Fact] - public async Task SaveCategoryFile_return_id_edit_record() + public async Task GetHistoryFileByIdCategory_return_empty_hitory() { - var stream = new FileStream("D:\\test\\test.txt", FileMode.Open); - var data = await service.SaveCategoryFileAsync(21, 10018, 78, stream, "test.txt", CancellationToken.None); - Assert.Equal(21, data); + var data = await service.GetFilesHistoryByIdCategoryAsync(1, 13 * idWellFinalDocCategory, CancellationToken.None); + Assert.NotNull(data); + Assert.Empty(data.Files); + } + + [Fact] + public async Task SaveCategoryFile_throws_wrong_user() + { + var content = new byte[] {0xAA, 0xBB}; + var stream = new MemoryStream(content); + await Assert.ThrowsAsync( + async () => await service.SaveCategoryFileAsync(21, 13 * idWellFinalDocCategory, 78, stream, "test.txt", CancellationToken.None) + ); + } + + [Fact] + public async Task SaveCategoryFile_returns_file_id() + { + var content = new byte[] { 0xAA, 0xBB }; + var stream = new MemoryStream(content); + var token = CancellationToken.None; + var idFile = await service.SaveCategoryFileAsync(1, idWellFinalDocCategory, users[0].Id, stream, "test.txt", CancellationToken.None); + Assert.Equal(validInsertedFileId, idFile); + fileRepositoryMock.Verify(m => m.InsertAsync(It.IsAny(), token)); + fileStorageRepositoryMock.Verify(m=>m.SaveFileAsync(It.IsAny(), stream, token)); + } + + [Fact] + public async Task ReNotifyPublishersAsync_deny_to_non_editors() + { + await Assert.ThrowsAsync( + async() => await service.ReNotifyPublishersAsync(1, users[1].Id, idWellFinalDocCategory, CancellationToken.None)); + } + + [Fact] + public async Task ReNotifyPublishersAsync_deny_to_non_wrong_category() + { + await Assert.ThrowsAsync( + async () => await service.ReNotifyPublishersAsync(1, users[0].Id, 13 * idWellFinalDocCategory, CancellationToken.None)); + } + + [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())); } } }