diff --git a/AsbCloudApp/AsbCloudApp.csproj b/AsbCloudApp/AsbCloudApp.csproj index 64a7b66a..7a10181c 100644 --- a/AsbCloudApp/AsbCloudApp.csproj +++ b/AsbCloudApp/AsbCloudApp.csproj @@ -13,4 +13,16 @@ + + + + + + + + + + + + diff --git a/AsbCloudApp/Services/IFileRepository.cs b/AsbCloudApp/Repositories/IFileRepository.cs similarity index 98% rename from AsbCloudApp/Services/IFileRepository.cs rename to AsbCloudApp/Repositories/IFileRepository.cs index e01891cc..e36d1001 100644 --- a/AsbCloudApp/Services/IFileRepository.cs +++ b/AsbCloudApp/Repositories/IFileRepository.cs @@ -1,10 +1,11 @@ using AsbCloudApp.Data; +using AsbCloudApp.Services; using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudApp.Services +namespace AsbCloudApp.Repositories { /// /// Сервис доступа к файлам diff --git a/AsbCloudApp/Repositories/IFileStorageRepository.cs b/AsbCloudApp/Repositories/IFileStorageRepository.cs new file mode 100644 index 00000000..9d821861 --- /dev/null +++ b/AsbCloudApp/Repositories/IFileStorageRepository.cs @@ -0,0 +1,51 @@ +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace AsbCloudApp.Repositories +{ + /// + /// Репозиторий хранения фалов + /// + public interface IFileStorageRepository + { + /// + /// Директория хранения файлов + /// + string RootPath { get; } + + /// + /// Получение длинны фала и проверка его наличия, если отсутствует падает исключение + /// + /// + /// + long GetLengthFile(string srcFilePath); + + /// + /// Перемещение файла + /// + /// + /// + void MoveFile(string srcFilePath, string filePath); + + /// + /// Копирование файла + /// + /// + Task CopyFileAsync(string filePath, Stream fileStream, CancellationToken token); + + /// + /// Удаление файла + /// + /// + void DeleteFile(string fileName); + + /// + /// Проверка наличия файла + /// + /// + /// + /// + bool FileExists(string fullPath, string fileName); + } +} diff --git a/AsbCloudInfrastructure/Services/FileService.cs b/AsbCloudApp/Services/FileService.cs similarity index 52% rename from AsbCloudInfrastructure/Services/FileService.cs rename to AsbCloudApp/Services/FileService.cs index cdfed260..b27c4383 100644 --- a/AsbCloudInfrastructure/Services/FileService.cs +++ b/AsbCloudApp/Services/FileService.cs @@ -1,10 +1,5 @@ using AsbCloudApp.Data; -using AsbCloudApp.Exceptions; -using AsbCloudApp.Services; -using AsbCloudDb.Model; -using AsbCloudInfrastructure.Repository; -using Mapster; -using Microsoft.EntityFrameworkCore; +using AsbCloudApp.Repositories; using System; using System.Collections.Generic; using System.IO; @@ -12,28 +7,43 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -namespace AsbCloudInfrastructure.Services +namespace AsbCloudApp.Services { - public class FileService : IFileService + /// + /// Сервис доступа к файлам + /// + public class FileService { - public string RootPath { get; private set; } private readonly IFileRepository fileRepository; + private readonly IFileStorageRepository fileStorageRepository; - public FileService(IFileRepository fileRepository) + /// + /// Сервис доступа к файлам + /// + /// + /// + public FileService(IFileRepository fileRepository, IFileStorageRepository fileStorageRepository) { - RootPath = "files"; this.fileRepository = fileRepository; + this.fileStorageRepository = fileStorageRepository; } + /// + /// переместить файл + /// + /// + /// + /// + /// + /// + /// + /// public async Task MoveAsync(int idWell, int? idUser, int idCategory, string destinationFileName, string srcFilePath, CancellationToken token = default) { destinationFileName = Path.GetFileName(destinationFileName); srcFilePath = Path.GetFullPath(srcFilePath); - if (!File.Exists(srcFilePath)) - throw new ArgumentInvalidException($"file {srcFilePath} doesn't exist", nameof(srcFilePath)); - - var sysFileInfo = new System.IO.FileInfo(srcFilePath); + var fileSize = fileStorageRepository.GetLengthFile(srcFilePath); //save info to db var dto = new FileInfoDto { @@ -41,18 +51,27 @@ namespace AsbCloudInfrastructure.Services IdAuthor = idUser, IdCategory = idCategory, Name = destinationFileName, - Size = sysFileInfo.Length + Size = fileSize }; var fileId = await fileRepository.InsertAsync(dto, token) .ConfigureAwait(false); string filePath = MakeFilePath(idWell, idCategory, destinationFileName, fileId); - Directory.CreateDirectory(Path.GetDirectoryName(filePath)); - File.Move(srcFilePath, filePath); + fileStorageRepository.MoveFile(srcFilePath, filePath); return await GetInfoAsync(fileId, token); } + /// + /// Сохранить файл + /// + /// + /// + /// + /// + /// + /// + /// public async Task SaveAsync(int idWell, int? idUser, int idCategory, string fileFullName, Stream fileStream, CancellationToken token) { @@ -71,21 +90,17 @@ namespace AsbCloudInfrastructure.Services //save stream to disk string filePath = MakeFilePath(idWell, idCategory, fileFullName, fileId); - - Directory.CreateDirectory(Path.GetDirectoryName(filePath)); - - using var newfileStream = new FileStream(filePath, FileMode.Create); - await fileStream.CopyToAsync(newfileStream, token).ConfigureAwait(false); + await fileStorageRepository.CopyFileAsync(filePath, fileStream, token); return await GetInfoAsync(fileId, token); } - private string MakeFilePath(int idWell, int idCategory, string fileFullName, int fileId) - { - return Path.Combine(RootPath, $"{idWell}", - $"{idCategory}", $"{fileId}" + $"{Path.GetExtension(fileFullName)}"); - } - + /// + /// Инфо о файле + /// + /// + /// + /// public async Task GetInfoAsync(int idFile, CancellationToken token) { @@ -95,17 +110,26 @@ namespace AsbCloudInfrastructure.Services var relativePath = GetUrl(dto.IdWell, dto.IdCategory, dto.Id, ext); var fullPath = Path.GetFullPath(relativePath); - if (!File.Exists(fullPath)) - { - throw new FileNotFoundException("not found", relativePath); - } + fileStorageRepository.FileExists(fullPath, relativePath); return dto; } + /// + /// удалить файл + /// + /// + /// + /// public Task DeleteAsync(int idFile, CancellationToken token) => DeleteAsync(new int[] { idFile }, token); + /// + /// удалить файлы + /// + /// + /// + /// public async Task DeleteAsync(IEnumerable ids, CancellationToken token) { if (ids is null || !ids.Any()) @@ -119,13 +143,17 @@ namespace AsbCloudInfrastructure.Services foreach (var file in files) { var fileName = GetUrl(file.IdWell, file.IdCategory, file.Id, Path.GetExtension(file.Name)); - if (File.Exists(fileName)) - File.Delete(fileName); + fileStorageRepository.DeleteFile(fileName); } return files.Any() ? 1 : 0; } + /// + /// получить путь для скачивания + /// + /// + /// public async Task GetUrl(int idFile) { var fileInfo = await fileRepository.GetOrDefaultAsync(idFile, CancellationToken.None).ConfigureAwait(false); @@ -133,16 +161,41 @@ namespace AsbCloudInfrastructure.Services return GetUrl(fileInfo.IdWell, fileInfo.IdCategory, fileInfo.Id, Path.GetExtension(fileInfo.Name)); } + /// + /// получить путь для скачивания + /// + /// + /// public string GetUrl(FileInfoDto fileInfo) => GetUrl(fileInfo.IdWell, fileInfo.IdCategory, fileInfo.Id, Path.GetExtension(fileInfo.Name)); + /// + /// получить путь для скачивания + /// + /// + /// + /// + /// + /// public string GetUrl(int idWell, int idCategory, int idFile, string dotExtention) => - Path.Combine(RootPath, idWell.ToString(), idCategory.ToString(), $"{idFile}{dotExtention}"); + Path.Combine(fileStorageRepository.RootPath, idWell.ToString(), idCategory.ToString(), $"{idFile}{dotExtention}"); + /// + /// пометить метку файла как удаленную + /// + /// + /// + /// public Task MarkFileMarkAsDeletedAsync(int idMark, CancellationToken token) => fileRepository.MarkFileMarkAsDeletedAsync(new int[] { idMark }, token); + /// + /// Инфо о файле + /// + /// + /// + /// public async Task> GetInfoByIdsAsync(IEnumerable idsFile, CancellationToken token) { var result = await fileRepository.GetInfoByIdsAsync(idsFile, token).ConfigureAwait(false); @@ -153,47 +206,107 @@ namespace AsbCloudInfrastructure.Services var ext = Path.GetExtension(entity.Name); var relativePath = GetUrl(entity.IdWell, entity.IdCategory, entity.Id, ext); var fullPath = Path.GetFullPath(relativePath); - if (!File.Exists(fullPath)) - { - throw new FileNotFoundException("not found", relativePath); - } + fileStorageRepository.FileExists(fullPath, relativePath); } - + return result; } + /// + /// Получить список файлов в контейнере + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public async Task> GetInfosAsync(int idWell, int idCategory, string companyName = default, string fileName = default, DateTime begin = default, DateTime end = default, int skip = 0, int take = 32, CancellationToken token = default) => await fileRepository.GetInfosAsync(idWell, idCategory, companyName, fileName, begin, end, skip, take, token) .ConfigureAwait(false); + /// + /// Пометить файл как удаленный + /// + /// + /// + /// public async Task MarkAsDeletedAsync(int idFile, CancellationToken token = default) => await fileRepository.MarkAsDeletedAsync(idFile, token) .ConfigureAwait(false); + /// + /// добавить метку на файл + /// + /// + /// + /// + /// public async Task CreateFileMarkAsync(FileMarkDto fileMarkDto, int idUser, CancellationToken token) => await fileRepository.CreateFileMarkAsync(fileMarkDto, idUser, token) .ConfigureAwait(false); + /// + /// Получить запись по id + /// + /// + /// + /// public async Task GetOrDefaultAsync(int id, CancellationToken token) => await fileRepository.GetOrDefaultAsync(id, token) .ConfigureAwait(false); + /// + /// получить инфо о файле по метке + /// + /// + /// + /// public async Task GetByMarkId(int idMark, CancellationToken token) => await fileRepository.GetByMarkId(idMark, token) .ConfigureAwait(false); + /// + /// получить инфо о файле по метке + /// + /// + /// + /// public async Task MarkFileMarkAsDeletedAsync(IEnumerable idsMarks, CancellationToken token) => await fileRepository.MarkFileMarkAsDeletedAsync(idsMarks, token) .ConfigureAwait(false); + /// + /// Получение файлов по скважине + /// + /// + /// + /// public async Task> GetInfosByWellIdAsync(int idWell, CancellationToken token) => await fileRepository.GetInfosByWellIdAsync(idWell, token) .ConfigureAwait(false); + /// + /// Получить файлы определенной категории + /// + /// + /// + /// + /// public async Task> GetInfosByCategoryAsync(int idWell, int idCategory, CancellationToken token) => await fileRepository.GetInfosByCategoryAsync(idWell, idCategory, token) .ConfigureAwait(false); + + private string MakeFilePath(int idWell, int idCategory, string fileFullName, int fileId) + { + return Path.Combine(fileStorageRepository.RootPath, $"{idWell}", + $"{idCategory}", $"{fileId}" + $"{Path.GetExtension(fileFullName)}"); + } } } diff --git a/AsbCloudApp/Services/IFileService.cs b/AsbCloudApp/Services/IFileService.cs deleted file mode 100644 index a83d6d5c..00000000 --- a/AsbCloudApp/Services/IFileService.cs +++ /dev/null @@ -1,186 +0,0 @@ -using AsbCloudApp.Data; -using System; -using System.Collections.Generic; -using System.IO; -using System.Threading; -using System.Threading.Tasks; - -namespace AsbCloudApp.Services -{ - //TODO: refactor IFileService - - /// - /// Сервис доступа к файлам - /// - public interface IFileService - { - /// - /// Директория хранения файлов - /// - string RootPath { get; } - - /// - /// Сохранить файл - /// - /// - /// - /// - /// - /// - /// - /// - Task SaveAsync(int idWell, int? idUser, int idCategory, string fileFullName, Stream fileStream, CancellationToken token = default); - - /// - /// Инфо о файле - /// - /// - /// - /// - Task GetInfoAsync(int idFile, - CancellationToken token); - - /// - /// удалить файл - /// - /// - /// - /// - Task DeleteAsync(int id, CancellationToken token); - - /// - /// удалить файлы - /// - /// - /// - /// - Task DeleteAsync(IEnumerable ids, CancellationToken token); - - /// - /// получить путь для скачивания - /// - /// - /// - string GetUrl(FileInfoDto fileInfo); - - /// - /// получить путь для скачивания - /// - /// - /// - Task GetUrl(int idFile); - - /// - /// получить путь для скачивания - /// - /// - /// - /// - /// - /// - string GetUrl(int idWell, int idCategory, int idFile, string dotExtention); - - /// - /// пометить метку файла как удаленную - /// - /// - /// - /// - Task MarkFileMarkAsDeletedAsync(int idMark, CancellationToken token); - - /// - /// переместить файл - /// - /// - /// - /// - /// - /// - /// - /// - Task MoveAsync(int idWell, int? idUser, int idCategory, string destinationFileName, string srcFileFullName, CancellationToken token = default); - - /// - /// Инфо о файле - /// - /// - /// - /// - Task> GetInfoByIdsAsync(IEnumerable idsFile, CancellationToken token); - - /// - /// Получить список файлов в контейнере - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - Task> GetInfosAsync(int idWell, - int idCategory, string companyName = default, string fileName = default, DateTime begin = default, - DateTime end = default, int skip = 0, int take = 32, CancellationToken token = default); - - /// - /// Пометить файл как удаленный - /// - /// - /// - /// - Task MarkAsDeletedAsync(int idFile, CancellationToken token = default); - - /// - /// добавить метку на файл - /// - /// - /// - /// - /// - Task CreateFileMarkAsync(FileMarkDto fileMarkDto, int idUser, CancellationToken token); - - /// - /// Получить запись по id - /// - /// - /// - /// - Task GetOrDefaultAsync(int id, CancellationToken token); - - /// - /// получить инфо о файле по метке - /// - /// - /// - /// - Task GetByMarkId(int idMark, CancellationToken token); - - /// - /// пометить метки файлов как удаленные - /// - /// - /// - /// - Task MarkFileMarkAsDeletedAsync(IEnumerable idsMarks, CancellationToken token); - - /// - /// Получение файлов по скважине - /// - /// - /// - /// - Task> GetInfosByWellIdAsync(int idWell, CancellationToken token); - - /// - /// Получить файлы определенной категории - /// - /// - /// - /// - /// - Task> GetInfosByCategoryAsync(int idWell, int idCategory, CancellationToken token); - } -} diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs index 1c69736d..53e2d792 100644 --- a/AsbCloudInfrastructure/DependencyInjection.cs +++ b/AsbCloudInfrastructure/DependencyInjection.cs @@ -1,6 +1,7 @@ using AsbCloudApp.Data; using AsbCloudApp.Data.SAUB; using AsbCloudApp.Data.Subsystems; +using AsbCloudApp.Repositories; using AsbCloudApp.Services; using AsbCloudApp.Services.Subsystems; using AsbCloudDb.Model; @@ -109,7 +110,7 @@ namespace AsbCloudInfrastructure services.AddTransient(); services.AddTransient(); services.AddTransient(); - services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); @@ -159,6 +160,7 @@ namespace AsbCloudInfrastructure .Include(c => c.Wells) .Include(c => c.Deposit))); // может быть включен в сервис ClusterService services.AddTransient(); + services.AddTransient(); // Subsystem service services.AddTransient, CrudCacheServiceBase>(); services.AddTransient(); diff --git a/AsbCloudInfrastructure/Repository/FileRepository.cs b/AsbCloudInfrastructure/Repository/FileRepository.cs index 2726c2b7..0cca5b8b 100644 --- a/AsbCloudInfrastructure/Repository/FileRepository.cs +++ b/AsbCloudInfrastructure/Repository/FileRepository.cs @@ -1,5 +1,5 @@ using AsbCloudApp.Data; -using AsbCloudApp.Services; +using AsbCloudApp.Repositories; using AsbCloudDb.Model; using Mapster; using Microsoft.EntityFrameworkCore; diff --git a/AsbCloudInfrastructure/Repository/FileStorageRepository.cs b/AsbCloudInfrastructure/Repository/FileStorageRepository.cs new file mode 100644 index 00000000..7466f3a3 --- /dev/null +++ b/AsbCloudInfrastructure/Repository/FileStorageRepository.cs @@ -0,0 +1,59 @@ +using AsbCloudApp.Exceptions; +using AsbCloudApp.Repositories; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace AsbCloudInfrastructure.Repository +{ + public class FileStorageRepository : IFileStorageRepository + { + public string RootPath { get; private set; } + + public FileStorageRepository() + { + RootPath = "files"; + } + + public async Task CopyFileAsync(string filePath, Stream fileStream, CancellationToken token) + { + CreateDirectory(filePath); + using var newfileStream = new FileStream(filePath, FileMode.Create); + await fileStream.CopyToAsync(newfileStream, token).ConfigureAwait(false); + } + + public void DeleteFile(string fileName) + { + if (File.Exists(fileName)) + File.Delete(fileName); + } + + public long GetLengthFile(string srcFilePath) + { + if (!File.Exists(srcFilePath)) + throw new ArgumentInvalidException($"file {srcFilePath} doesn't exist", nameof(srcFilePath)); + + var sysFileInfo = new FileInfo(srcFilePath); + return sysFileInfo.Length; + } + + public void MoveFile(string srcFilePath, string filePath) + { + CreateDirectory(filePath); + File.Move(srcFilePath, filePath); + } + + public bool FileExists(string fullPath, string fileName) + { + if (!File.Exists(fullPath)) + throw new FileNotFoundException("not found", fileName); + + return true; + } + + private void CreateDirectory(string filePath) + { + Directory.CreateDirectory(Path.GetDirectoryName(filePath)); + } + } +} diff --git a/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs b/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs index 0e840524..ca0827b0 100644 --- a/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs +++ b/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs @@ -20,7 +20,7 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram private static readonly Dictionary drillingProgramCreateErrors = new Dictionary(); private readonly IAsbCloudDbContext context; - private readonly IFileService fileService; + private readonly FileService fileService; private readonly IUserService userService; private readonly IWellService wellService; private readonly IConfiguration configuration; @@ -50,7 +50,7 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram public DrillingProgramService( IAsbCloudDbContext context, - IFileService fileService, + FileService fileService, IUserService userService, IWellService wellService, IConfiguration configuration, @@ -481,7 +481,8 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram .Options; using var context = new AsbCloudDbContext(contextOptions); var fileRepository = new FileRepository(context); - var fileService = new FileService(fileRepository); + var fileStorageRepository = new FileStorageRepository(); + var fileService = new FileService(fileRepository, fileStorageRepository); var files = state.Parts.Select(p => fileService.GetUrl(p.File)); DrillingProgramMaker.UniteExcelFiles(files, tempResultFilePath, state.Parts, well); await fileService.MoveAsync(idWell, null, idFileCategoryDrillingProgram, resultFileName, tempResultFilePath, token); diff --git a/AsbCloudInfrastructure/Services/ReportService.cs b/AsbCloudInfrastructure/Services/ReportService.cs index 53d8653a..7d60f852 100644 --- a/AsbCloudInfrastructure/Services/ReportService.cs +++ b/AsbCloudInfrastructure/Services/ReportService.cs @@ -67,7 +67,8 @@ namespace AsbCloudInfrastructure.Services generator.Make(reportFileName); var fileRepository = new FileRepository(context); - var fileService = new FileService(fileRepository); + var fileStorageRepository = new FileStorageRepository(); + var fileService = new FileService(fileRepository, fileStorageRepository); var fileInfo = await fileService.MoveAsync(idWell, idUser, ReportCategoryId, reportFileName, reportFileName, token); progressHandler.Invoke(new diff --git a/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs b/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs index 4d5f6427..62d82522 100644 --- a/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs +++ b/AsbCloudInfrastructure/Services/WellFinalDocumentsService.cs @@ -22,7 +22,7 @@ namespace AsbCloudInfrastructure.Services public class WellFinalDocumentsService : IWellFinalDocumentsService { private readonly IAsbCloudDbContext context; - private readonly IFileService fileService; + private readonly FileService fileService; private readonly IUserService userService; private readonly IWellService wellService; private readonly IConfiguration configuration; @@ -32,7 +32,7 @@ namespace AsbCloudInfrastructure.Services private const int FileServiceThrewException = -1; public WellFinalDocumentsService(IAsbCloudDbContext context, - IFileService fileService, + FileService fileService, IUserService userService, IWellService wellService, IConfiguration configuration, diff --git a/AsbCloudWebApi.Tests/IRepositoryFactory.cs b/AsbCloudWebApi.Tests/IRepositoryFactory.cs new file mode 100644 index 00000000..e7028689 --- /dev/null +++ b/AsbCloudWebApi.Tests/IRepositoryFactory.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace AsbCloudWebApi.Tests +{ + public interface IRepositoryFactory + { + Task DeleteAsync(int id, CancellationToken token); + Task> GetAllAsync(CancellationToken token); + TDto? GetOrDefault(int id); + Task GetOrDefaultAsync(int id, CancellationToken token); + Task InsertAsync(TDto newItem, CancellationToken token); + Task InsertRangeAsync(IEnumerable newItems, CancellationToken token); + Task UpdateAsync(TDto item, CancellationToken token); + } +} \ No newline at end of file diff --git a/AsbCloudWebApi.Tests/RepositoryFactory.cs b/AsbCloudWebApi.Tests/RepositoryFactory.cs new file mode 100644 index 00000000..a8588dda --- /dev/null +++ b/AsbCloudWebApi.Tests/RepositoryFactory.cs @@ -0,0 +1,42 @@ +using AsbCloudApp.Services; +using Moq; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace AsbCloudWebApi.Tests +{ + public class RepositoryFactory + { + public static Mock Make(ICollection data) + where TDto : AsbCloudApp.Data.IId + where TRepository : class, ICrudService + { + var repositoryMock = new Mock(); + + repositoryMock.Setup(x => x.InsertAsync(It.IsAny(), It.IsAny())) + .Returns((TDto dto, CancellationToken token) => { + var id = data.Max(x => x.Id); + dto.Id = ++id; + data.Add(dto); + return Task.FromResult(dto.Id); + }); + repositoryMock.Setup(x => x.DeleteAsync(It.IsAny(), It.IsAny())) + .Returns((int idFile, CancellationToken token) => { + var cnt = data.Count; + var dto = data.FirstOrDefault(x => x.Id == idFile); + data.Remove(dto); + return Task.FromResult(cnt - data.Count); + }); + + repositoryMock.Setup(x => x.GetAllAsync(It.IsAny())).ReturnsAsync(data); + repositoryMock.Setup(x => x.GetOrDefaultAsync(It.IsAny(), It.IsAny())) + .Returns((int idFile, CancellationToken token) => { + return Task.FromResult(data.FirstOrDefault(x => x.Id == idFile)); + }); + + return repositoryMock; + } + } +} diff --git a/AsbCloudWebApi.Tests/ServicesTests/DrillingProgramServiceTest.cs b/AsbCloudWebApi.Tests/ServicesTests/DrillingProgramServiceTest.cs index 949c8c46..fa72df35 100644 --- a/AsbCloudWebApi.Tests/ServicesTests/DrillingProgramServiceTest.cs +++ b/AsbCloudWebApi.Tests/ServicesTests/DrillingProgramServiceTest.cs @@ -78,7 +78,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests new RelationCompanyWell { IdCompany = 3003, IdWell = 3002, }, }; - private readonly Mock fileServiceMock; + private readonly Mock fileServiceMock; private readonly Mock userServiceMock; private readonly Mock wellServiceMock; private readonly Mock configurationMock; @@ -97,7 +97,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests db.RelationCompaniesWells.AddRange(relationsCompanyWell); db.SaveChanges(); - fileServiceMock = new Mock(); + fileServiceMock = new Mock(); userServiceMock = new Mock(); wellServiceMock = new Mock(); configurationMock = new Mock(); diff --git a/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs b/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs new file mode 100644 index 00000000..025cc7bb --- /dev/null +++ b/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs @@ -0,0 +1,224 @@ +using AsbCloudApp.Data; +using AsbCloudApp.Repositories; +using AsbCloudApp.Services; +using AsbCloudDb.Model; +using AsbCloudInfrastructure.Repository; +using AsbCloudInfrastructure.Services; +using DocumentFormat.OpenXml.Spreadsheet; +using DocumentFormat.OpenXml.Wordprocessing; +using Moq; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Xunit; +using static AsbCloudWebApi.Tests.TestHelpter; + +namespace AsbCloudWebApi.Tests.ServicesTests +{ + public class FileServiceTest + { + private FileService fileService; + + private static UserDto Author = new UserDto { + Id = 1, + IdCompany = 1 + }; + + private static List FileMarks = new List { + new FileMarkDto + { + Id = 132, + IdFile = 1742, + User = Author, + Comment = "qqq", + IdMarkType = 1, + DateCreated = DateTime.Now, + IsDeleted = false + }, + new FileMarkDto + { + Id = 133, + IdFile = 1742, + User = Author, + Comment = "qqq3", + IdMarkType = 1, + DateCreated = DateTime.Now, + IsDeleted = false + } + }; + + private static List Files = new List { + new FileInfoDto { + Id = 1742, + IdAuthor = 1, + Author = Author, + IdWell = 90, + IdCategory = 10040, + Name = "test.txt", + Size = 0, + UploadDate = DateTime.Now, + FileMarks = FileMarks + }, + new FileInfoDto + { + Id = 1743, + IdAuthor = 1, + Author = Author, + IdWell = 90, + IdCategory = 10021, + Name = "test1.txt", + Size = 0, + UploadDate = DateTime.Now + } + }; + + public FileServiceTest() + { + var repositoryMock = RepositoryFactory.Make(Files); + + repositoryMock.Setup(x => x.GetByMarkId(It.IsAny(), It.IsAny())) + .Returns((int idMark, CancellationToken token) => { + var data = Files.FirstOrDefault(x => x.FileMarks.Any(m => m.Id == idMark)); + return Task.FromResult(data); + }); + repositoryMock.Setup(x => x.GetInfoByIdsAsync(It.IsAny>(), It.IsAny())) + .Returns((int[] idsFile, CancellationToken token) => { + var data = Files.Where(x => idsFile.Contains(x.Id)); + return Task.FromResult(data); + }); + + repositoryMock.Setup(x => x.DeleteAsync(It.IsAny>(), It.IsAny())) + .Returns((int[] idsFile, CancellationToken token) => { + var dtos = Files.Where(x => idsFile.Contains(x.Id)).ToArray(); + Files.RemoveAll(x => dtos.Select(d => d.Id).Contains(x.Id)); + return Task.FromResult(dtos.AsEnumerable()); + }); + + repositoryMock.Setup(x => x.MarkFileMarkAsDeletedAsync(It.IsAny>(), It.IsAny())) + .Returns((int[] idsMarks, CancellationToken token) => { + var data = FileMarks.Where(m => idsMarks.Contains(m.Id)); + + foreach (var fileMark in data) + fileMark.IsDeleted = true; + + var result = data.All(x => x.IsDeleted) ? 1 : 0; + return Task.FromResult(result); + }); + + repositoryMock.Setup(x => x.MarkAsDeletedAsync(It.IsAny(), It.IsAny())) + .Returns((int idFile, CancellationToken token) => { + var result = Files.Where(x => x.Id == idFile).Any() ? 1 : 0; + return Task.FromResult(result); + }); + + repositoryMock.Setup(x => x.GetInfosByWellIdAsync(It.IsAny(), It.IsAny())) + .Returns((int idWell, CancellationToken token) => { + var data = Files.Where(x => x.IdWell == idWell); + return Task.FromResult(data); + }); + + repositoryMock.Setup(x => x.GetInfosByCategoryAsync(It.IsAny(), It.IsAny(), It.IsAny())) + .Returns((int idWell, int idCategory, CancellationToken token) => { + var data = Files.Where(x => x.IdWell == idWell && x.IdCategory == idCategory); + return Task.FromResult(data); + }); + + repositoryMock.Setup(x => x.CreateFileMarkAsync(It.IsAny(), It.IsAny(), It.IsAny())) + .Returns((FileMarkDto dto, int idUser, CancellationToken token) => { + dto.Id = FileMarks.Max(x => x.Id) + 1; + dto.DateCreated = DateTime.UtcNow; + dto.User = null; + FileMarks.Add(dto); + + var result = FileMarks.Any(x => x.Id == dto.Id) ? 1 : 0; + return Task.FromResult(result); + }); + + var storageRepositoryMock = new Mock(); + + storageRepositoryMock.Setup(x => x.RootPath).Returns("files"); + + fileService = new FileService(repositoryMock.Object, storageRepositoryMock.Object); + } + + [Fact] + public async Task GetByMarkId_returns_FileInfo_by_idMark() + { + var data = await fileService.GetByMarkId(133, CancellationToken.None); + Assert.NotNull(data); + } + + [Fact] + public async Task GetInfoAsync_returns_FileInfo() + { + var data = await fileService.GetInfoAsync(1742, CancellationToken.None); + Assert.NotNull(data); + } + + [Fact] + public async Task GetInfoByIdsAsync_returns_FileInfo() + { + var data = await fileService.GetInfoByIdsAsync(new int[] { 1742, 1743 }, CancellationToken.None); + Assert.NotNull(data); + } + + [Fact] + public async Task SaveAsync_returns_FileInfo() + { + using var stream = new MemoryStream(Array.Empty()); + var data = await fileService.SaveAsync(90, 1, 10040, "test.txt", stream, CancellationToken.None); + Assert.NotNull(data); + } + + [Fact] + public async Task DeleteAsync() + { + var result = await fileService.DeleteAsync(new int[] { 1743 }, CancellationToken.None); + Assert.True(result > 0); + } + + [Fact] + public async Task MarkFileMarkAsDeletedAsync() + { + var result = await fileService.MarkFileMarkAsDeletedAsync(new int[] { 132, 133 }, CancellationToken.None); + Assert.True(result > 0); + } + + [Fact] + public async Task MarkAsDeletedAsync() + { + var result = await fileService.MarkAsDeletedAsync(1742, CancellationToken.None); + Assert.True(result > 0); + } + + [Fact] + public async Task GetInfosByWellIdAsync_returns_FileInfo() + { + var data = await fileService.GetInfosByWellIdAsync(90, CancellationToken.None); + Assert.NotNull(data); + } + + [Fact] + public async Task GetInfosByCategoryAsync_returns_FileInfo() + { + var data = await fileService.GetInfosByCategoryAsync(90, 10040, CancellationToken.None); + Assert.NotNull(data); + } + + [Fact] + public async Task CreateFileMarkAsync() + { + var dto = new FileMarkDto { + Comment = "test", + IdFile = 1742, + IdMarkType = 1 + }; + var result = await fileService.CreateFileMarkAsync(dto, 1, CancellationToken.None); + Assert.True(result > 0); + } + } +} diff --git a/AsbCloudWebApi.Tests/ServicesTests/WellFinalDocumentsServiceTest.cs b/AsbCloudWebApi.Tests/ServicesTests/WellFinalDocumentsServiceTest.cs index ac53a5b9..1718b92d 100644 --- a/AsbCloudWebApi.Tests/ServicesTests/WellFinalDocumentsServiceTest.cs +++ b/AsbCloudWebApi.Tests/ServicesTests/WellFinalDocumentsServiceTest.cs @@ -17,7 +17,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests { private readonly AsbCloudDbContext context; private WellFinalDocumentsService service; - private readonly Mock fileServiceMock; + private readonly Mock fileServiceMock; private readonly Mock userServiceMock; private readonly Mock wellServiceMock; private readonly Mock configurationMock; @@ -44,7 +44,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests context = TestHelpter.MakeTestContext(); context.SaveChanges(); - fileServiceMock = new Mock(); + fileServiceMock = new Mock(); userServiceMock = new Mock(); userServiceMock.Setup(x => x.GetAllAsync(CancellationToken.None)).Returns(Task.Run(() => users.Select(x => (UserExtendedDto)x))); diff --git a/AsbCloudWebApi.Tests/TestHelpter.cs b/AsbCloudWebApi.Tests/TestHelpter.cs index 9322503b..f7c8e8a9 100644 --- a/AsbCloudWebApi.Tests/TestHelpter.cs +++ b/AsbCloudWebApi.Tests/TestHelpter.cs @@ -1,4 +1,5 @@ -using AsbCloudDb.Model; +using AsbCloudApp.Services; +using AsbCloudDb.Model; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Diagnostics; diff --git a/AsbCloudWebApi/Controllers/FileController.cs b/AsbCloudWebApi/Controllers/FileController.cs index a7711247..378b5a50 100644 --- a/AsbCloudWebApi/Controllers/FileController.cs +++ b/AsbCloudWebApi/Controllers/FileController.cs @@ -20,10 +20,10 @@ namespace AsbCloudWebApi.Controllers [Authorize] public class FileController : ControllerBase { - private readonly IFileService fileService; + private readonly FileService fileService; private readonly IWellService wellService; - public FileController(IFileService fileService, IWellService wellService) + public FileController(FileService fileService, IWellService wellService) { this.fileService = fileService; this.wellService = wellService; diff --git a/AsbCloudWebApi/Controllers/ReportController.cs b/AsbCloudWebApi/Controllers/ReportController.cs index 03897582..d3df1092 100644 --- a/AsbCloudWebApi/Controllers/ReportController.cs +++ b/AsbCloudWebApi/Controllers/ReportController.cs @@ -18,12 +18,12 @@ namespace AsbCloudWebApi.Controllers public class ReportController : ControllerBase { private readonly IReportService reportService; - private readonly IFileService fileService; + private readonly FileService fileService; private readonly IWellService wellService; private readonly IHubContext reportsHubContext; public ReportController(IReportService reportService, IWellService wellService, - IFileService fileService, IHubContext reportsHubContext) + FileService fileService, IHubContext reportsHubContext) { this.reportService = reportService; this.fileService = fileService;