diff --git a/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationImportService.cs b/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationImportService.cs index b8042275..3ed21dc2 100644 --- a/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationImportService.cs +++ b/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationImportService.cs @@ -5,20 +5,24 @@ using System.Linq; using AsbCloudApp.Data; using AsbCloudApp.Data.WellOperationImport; using AsbCloudApp.Repositories; +using AsbCloudApp.Services; using AsbCloudApp.Services.WellOperationImport; namespace AsbCloudInfrastructure.Services.WellOperationImport; public class WellOperationImportService : IWellOperationImportService { + private readonly IWellService wellService; private readonly IWellOperationRepository wellOperationRepository; private static readonly DateTime dateLimitMin = new(2001, 1, 1, 0, 0, 0); private static readonly DateTime dateLimitMax = new(2099, 1, 1, 0, 0, 0); private static readonly TimeSpan drillingDurationLimitMax = TimeSpan.FromDays(366); - public WellOperationImportService(IWellOperationRepository wellOperationRepository) + public WellOperationImportService(IWellService wellService, + IWellOperationRepository wellOperationRepository) { + this.wellService = wellService; this.wellOperationRepository = wellOperationRepository; } @@ -30,8 +34,12 @@ public class WellOperationImportService : IWellOperationImportService var categories = wellOperationRepository.GetCategories(false); var wellOperations = new List(); - - foreach (var row in sheet.Rows) + + var rows = sheet.Rows.OrderBy(r => r.Date); + + var prevRow = new RowDto(); + + foreach (var row in rows) { try { @@ -58,15 +66,16 @@ public class WellOperationImportService : IWellOperationImportService if (row.Date < dateLimitMin && row.Date > dateLimitMax) throw new FileFormatException( $"Лист '{sheet.Name}'. Строка '{row.Number}' неправильно получена дата начала операции"); - - if (wellOperations.LastOrDefault()?.DateStart > row.Date) + + if (prevRow.Date > row.Date) throw new FileFormatException( $"Лист '{sheet.Name}' строка '{row.Number}' дата позднее даты предыдущей операции"); if (row.Duration is not (>= 0d and <= 240d)) throw new FileFormatException($"Лист '{sheet.Name}'. Строка '{row.Number}' некорректная длительность операции"); - wellOperations.Add(new WellOperationDto + var timezone = wellService.GetTimezone(idWell); + var wellOperation = new WellOperationDto { IdWell = idWell, IdUser = idUser, @@ -76,10 +85,14 @@ public class WellOperationImportService : IWellOperationImportService CategoryInfo = row.CategoryInfo, DepthStart = row.DepthStart, DepthEnd = row.DepthEnd, - DateStart = row.Date, + DateStart = row.Date.ToUtcDateTimeOffset(timezone.Hours).ToRemoteDateTime(timezone.Hours), DurationHours = row.Duration, Comment = row.Comment - }); + }; + + wellOperations.Add(wellOperation); + + prevRow = row; } catch (FileFormatException ex) { diff --git a/AsbCloudWebApi.IntegrationTests/AsbCloudWebApi.IntegrationTests.csproj b/AsbCloudWebApi.IntegrationTests/AsbCloudWebApi.IntegrationTests.csproj index f20fc316..dcf078a9 100644 --- a/AsbCloudWebApi.IntegrationTests/AsbCloudWebApi.IntegrationTests.csproj +++ b/AsbCloudWebApi.IntegrationTests/AsbCloudWebApi.IntegrationTests.csproj @@ -18,6 +18,14 @@ + + + + + + + + diff --git a/AsbCloudWebApi.IntegrationTests/Clients/IWellOperationClient.cs b/AsbCloudWebApi.IntegrationTests/Clients/IWellOperationClient.cs index 07754ed1..8e2db98f 100644 --- a/AsbCloudWebApi.IntegrationTests/Clients/IWellOperationClient.cs +++ b/AsbCloudWebApi.IntegrationTests/Clients/IWellOperationClient.cs @@ -6,16 +6,22 @@ namespace AsbCloudWebApi.IntegrationTests.Clients; public interface IWellOperationClient { - private const string BaseRoute = "/api/well/{idWell}/wellOperations"; + private const string BaseRoute = "/api/well/{idWell}/wellOperations"; - [Post(BaseRoute + "/{idType}/{deleteBeforeInsert}")] - Task> InsertRangeAsync(int idWell, int idType, bool deleteBeforeInsert, [Body] IEnumerable dtos); + [Post(BaseRoute + "/{idType}/{deleteBeforeInsert}")] + Task> InsertRangeAsync(int idWell, int idType, bool deleteBeforeInsert, [Body] IEnumerable dtos); - [Put(BaseRoute + "/{idOperation}")] - Task> UpdateAsync(int idWell, int idOperation, [Body] WellOperationDto value, CancellationToken token); + [Put(BaseRoute + "/{idOperation}")] + Task> UpdateAsync(int idWell, int idOperation, [Body] WellOperationDto value, CancellationToken token); [Get(BaseRoute + "/plan")] Task>> GetPageOperationsPlanAsync(int idWell, [Query] WellOperationRequestBase request, CancellationToken token); + + [Multipart] + [Post(BaseRoute + "/import/plan/default")] + Task>> ImportPlanDefaultExcelFileAsync(int idWell, + [AliasAs("files")] IEnumerable streams, + CancellationToken token); } \ No newline at end of file diff --git a/AsbCloudWebApi.IntegrationTests/Controllers/WellOperationControllerTest.cs b/AsbCloudWebApi.IntegrationTests/Controllers/WellOperationControllerTest.cs index a5e0064a..51f6ab0e 100644 --- a/AsbCloudWebApi.IntegrationTests/Controllers/WellOperationControllerTest.cs +++ b/AsbCloudWebApi.IntegrationTests/Controllers/WellOperationControllerTest.cs @@ -2,7 +2,9 @@ using AsbCloudApp.Data; using AsbCloudDb.Model; using AsbCloudWebApi.IntegrationTests.Clients; using System.Net; +using System.Reflection; using AsbCloudApp.Requests; +using Refit; using Xunit; namespace AsbCloudWebApi.IntegrationTests.Controllers; @@ -211,4 +213,39 @@ public class WellOperationControllerTest : BaseIntegrationTest var excludeProps = new[] { nameof(WellOperationDto.Id) }; MatchHelper.Match(dto, wellOperation, excludeProps); } + + [Fact] + public async Task ImportPlanDefaultExcelFileAsync_returns_success() + { + //arrange + const int timeZoneUtc = 5; + + //TODO: вынести в метод расширения. Сделать когда доберёмся до рефакторинга операций по скважине + var resourceName = Assembly.GetExecutingAssembly() + .GetManifestResourceNames() + .FirstOrDefault(n => n.EndsWith("WellOperationsPlan.xlsx")); + + if (string.IsNullOrWhiteSpace(resourceName)) + throw new ArgumentNullException(nameof(resourceName)); + + var stream = Assembly.GetExecutingAssembly() + .GetManifestResourceStream(resourceName); + + if (stream is null) + throw new ArgumentNullException(nameof(stream)); + + var memoryStream = new MemoryStream(); + stream.CopyTo(memoryStream); + memoryStream.Position = 0; + + //act + var streamPart = new StreamPart(memoryStream, "WellOperations.xlsx", "application/octet-stream"); + + var response = await client.ImportPlanDefaultExcelFileAsync(idWell, new[] { streamPart }, CancellationToken.None); + + //assert + Assert.NotNull(response.Content); + Assert.Equal(4, response.Content.Count()); + Assert.True(response.Content.All(w => Math.Abs(w.DateStart.Offset.Hours - timeZoneUtc) < 0.1)); + } } \ No newline at end of file diff --git a/AsbCloudWebApi.IntegrationTests/WellOperationsPlan.xlsx b/AsbCloudWebApi.IntegrationTests/WellOperationsPlan.xlsx new file mode 100644 index 00000000..dd1a2781 Binary files /dev/null and b/AsbCloudWebApi.IntegrationTests/WellOperationsPlan.xlsx differ