Фикс часовых поясов + покрытие этого бага тестами

This commit is contained in:
Степанов Дмитрий 2024-02-06 11:41:51 +05:00
parent 3b7616ba43
commit 20172a886b
5 changed files with 77 additions and 13 deletions

View File

@ -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<WellOperationDto>();
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)
{

View File

@ -18,6 +18,14 @@
</PackageReference>
</ItemGroup>
<ItemGroup>
<None Remove="WellOperationsPlan.xlsx" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="WellOperationsPlan.xlsx" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AsbCloudWebApi\AsbCloudWebApi.csproj" />
</ItemGroup>

View File

@ -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<IApiResponse<int>> InsertRangeAsync(int idWell, int idType, bool deleteBeforeInsert, [Body] IEnumerable<WellOperationDto> dtos);
[Post(BaseRoute + "/{idType}/{deleteBeforeInsert}")]
Task<IApiResponse<int>> InsertRangeAsync(int idWell, int idType, bool deleteBeforeInsert, [Body] IEnumerable<WellOperationDto> dtos);
[Put(BaseRoute + "/{idOperation}")]
Task<IApiResponse<int>> UpdateAsync(int idWell, int idOperation, [Body] WellOperationDto value, CancellationToken token);
[Put(BaseRoute + "/{idOperation}")]
Task<IApiResponse<int>> UpdateAsync(int idWell, int idOperation, [Body] WellOperationDto value, CancellationToken token);
[Get(BaseRoute + "/plan")]
Task<IApiResponse<PaginationContainer<WellOperationDto>>> GetPageOperationsPlanAsync(int idWell,
[Query] WellOperationRequestBase request,
CancellationToken token);
[Multipart]
[Post(BaseRoute + "/import/plan/default")]
Task<IApiResponse<IEnumerable<WellOperationDto>>> ImportPlanDefaultExcelFileAsync(int idWell,
[AliasAs("files")] IEnumerable<StreamPart> streams,
CancellationToken token);
}

View File

@ -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));
}
}