forked from ddrilling/AsbCloudServer
Валидация вставки / обновления + интеграционные тесты (начало)
This commit is contained in:
parent
f9504aea21
commit
011a479a4b
@ -2,6 +2,7 @@
|
|||||||
using AsbCloudApp.Requests;
|
using AsbCloudApp.Requests;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@ -120,7 +121,7 @@ namespace AsbCloudApp.Repositories
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="wellOperations"></param>
|
/// <param name="wellOperations"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
bool Validate(IEnumerable<WellOperationDto> wellOperations);
|
IEnumerable<ValidationResult> Validate(IEnumerable<WellOperationDto> wellOperations);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Валидация данных (проверка с базой)
|
/// Валидация данных (проверка с базой)
|
||||||
@ -128,6 +129,6 @@ namespace AsbCloudApp.Repositories
|
|||||||
/// <param name="wellOperations"></param>
|
/// <param name="wellOperations"></param>
|
||||||
/// <param name="cancellationToken"></param>
|
/// <param name="cancellationToken"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<bool> ValidateWithDbAsync(IEnumerable<WellOperationDto> wellOperations, CancellationToken cancellationToken);
|
IEnumerable<ValidationResult> ValidateWithDbAsync(IEnumerable<WellOperationDto> wellOperations, CancellationToken cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -9,6 +9,7 @@ using Microsoft.EntityFrameworkCore;
|
|||||||
using Microsoft.Extensions.Caching.Memory;
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -333,12 +334,12 @@ public class WellOperationRepository : IWellOperationRepository
|
|||||||
return dtos;
|
return dtos;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> ValidateWithDbAsync(IEnumerable<WellOperationDto> wellOperationDtos, CancellationToken token)
|
public IEnumerable<ValidationResult> ValidateWithDbAsync(IEnumerable<WellOperationDto> wellOperationDtos, CancellationToken token)
|
||||||
{
|
{
|
||||||
var firstOperation = wellOperationDtos
|
var firstOperation = wellOperationDtos
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
if (firstOperation is null)
|
if (firstOperation is null)
|
||||||
return false;
|
return Enumerable.Empty<ValidationResult>();
|
||||||
|
|
||||||
var request = new WellOperationRequest()
|
var request = new WellOperationRequest()
|
||||||
{
|
{
|
||||||
@ -346,53 +347,51 @@ public class WellOperationRepository : IWellOperationRepository
|
|||||||
OperationType = firstOperation.IdType,
|
OperationType = firstOperation.IdType,
|
||||||
};
|
};
|
||||||
|
|
||||||
var entities = await BuildQuery(request)
|
var entities = BuildQuery(request)
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.ToArrayAsync(token)
|
.ToArray();
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
if (!entities.Any())
|
var wellOperationsUnion = entities.Union(wellOperationDtos).OrderBy(o => o.DateStart);
|
||||||
return Validate(wellOperationDtos);
|
|
||||||
|
|
||||||
var wellOperationsUnion = entities.Union(wellOperationDtos).OrderBy(o => o.DateStart).ToArray();
|
return Validate(wellOperationsUnion);
|
||||||
|
}
|
||||||
|
|
||||||
for(var i = 1; i < wellOperationsUnion.Count(); i++)
|
public IEnumerable<ValidationResult> Validate(IEnumerable<WellOperationDto> wellOperationDtos)
|
||||||
|
{
|
||||||
|
var firstOperation = wellOperationDtos
|
||||||
|
.FirstOrDefault();
|
||||||
|
if (firstOperation is null)
|
||||||
|
return Enumerable.Empty<ValidationResult>();
|
||||||
|
|
||||||
|
var validationResults = new List<ValidationResult>();
|
||||||
|
|
||||||
|
var wellOperations = wellOperationDtos.ToArray();
|
||||||
|
for (var i = wellOperations.Count() - 1; i >= 1; i--)
|
||||||
{
|
{
|
||||||
var prevOperation = wellOperationsUnion[i - 1];
|
var prevOperation = wellOperations[i - 1];
|
||||||
var currentOperation = wellOperationsUnion[i];
|
var currentOperation = wellOperations[i];
|
||||||
|
|
||||||
var prevOperationDateStart = prevOperation.DateStart.ToUniversalTime();
|
var prevOperationDateStart = prevOperation.DateStart.ToUniversalTime();
|
||||||
var currentOperationDateStart = currentOperation.DateStart.ToUniversalTime();
|
var currentOperationDateStart = currentOperation.DateStart.ToUniversalTime();
|
||||||
|
|
||||||
var prevOperationDateEnd = prevOperation.DateStart.AddHours(prevOperation.DurationHours).ToUniversalTime();
|
var prevOperationDateEnd = prevOperation.DateStart.AddHours(prevOperation.DurationHours).ToUniversalTime();
|
||||||
var currrentOperationDateEnd = currentOperation.DateStart.AddHours(currentOperation.DurationHours).ToUniversalTime();
|
|
||||||
|
|
||||||
if (currentOperation.Id == 0 && ((prevOperationDateStart.AddDays(Gap) < currentOperationDateStart) || (prevOperationDateEnd >= currrentOperationDateEnd)))
|
if (prevOperationDateStart.AddDays(Gap) < currentOperationDateStart)
|
||||||
{
|
{
|
||||||
return false;
|
validationResults.Add(new ValidationResult(
|
||||||
|
$"Разница дат между операциями не должна превышать 90 дней",
|
||||||
|
new[] { nameof(wellOperations) }));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevOperationDateEnd > currentOperationDateStart)
|
||||||
|
{
|
||||||
|
validationResults.Add(new ValidationResult(
|
||||||
|
$"Предыдущая операция не завершена",
|
||||||
|
new[] { nameof(wellOperations) }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Validate(IEnumerable<WellOperationDto> wellOperationDtos)
|
return validationResults;
|
||||||
{
|
|
||||||
var firstOperation = wellOperationDtos
|
|
||||||
.FirstOrDefault();
|
|
||||||
if (firstOperation is null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
var maxOperationDateStart = firstOperation.DateStart.ToUniversalTime();
|
|
||||||
|
|
||||||
foreach (var dto in wellOperationDtos)
|
|
||||||
{
|
|
||||||
var currentOperationDateStart = dto.DateStart.ToUniversalTime();
|
|
||||||
if (maxOperationDateStart.AddDays(Gap) < currentOperationDateStart)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
maxOperationDateStart = currentOperationDateStart;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
using AsbCloudApp.Data;
|
||||||
|
using AsbCloudApp.Data.ProcessMapPlan;
|
||||||
|
using AsbCloudApp.Requests;
|
||||||
|
using Refit;
|
||||||
|
|
||||||
|
namespace AsbCloudWebApi.IntegrationTests.Clients;
|
||||||
|
|
||||||
|
public interface IWellOperationClient
|
||||||
|
{
|
||||||
|
private const string BaseRoute = "/api/wellOperation";
|
||||||
|
|
||||||
|
[Post(BaseRoute)]
|
||||||
|
Task<IApiResponse<int>> InsertRange(int idWell, [Body] IEnumerable<WellOperationDto> dtos);
|
||||||
|
}
|
@ -0,0 +1,115 @@
|
|||||||
|
using AsbCloudApp.Data;
|
||||||
|
using AsbCloudApp.Data.ProcessMapPlan;
|
||||||
|
using AsbCloudApp.Requests;
|
||||||
|
using AsbCloudDb.Model;
|
||||||
|
using AsbCloudDb.Model.ProcessMaps;
|
||||||
|
using AsbCloudWebApi.IntegrationTests.Clients;
|
||||||
|
using System.Net;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace AsbCloudWebApi.IntegrationTests.Controllers;
|
||||||
|
|
||||||
|
|
||||||
|
public class WellOperationControllerTest : BaseIntegrationTest
|
||||||
|
{
|
||||||
|
private readonly int idWell = 4;
|
||||||
|
|
||||||
|
private readonly WellOperationDto[] dtos = new WellOperationDto[]
|
||||||
|
{
|
||||||
|
new WellOperationDto()
|
||||||
|
{
|
||||||
|
|
||||||
|
},
|
||||||
|
new WellOperationDto()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private IWellOperationClient wellOperationClient;
|
||||||
|
|
||||||
|
public WellOperationControllerTest(WebAppFactoryFixture factory)
|
||||||
|
: base(factory)
|
||||||
|
{
|
||||||
|
wellOperationClient = factory.GetAuthorizedHttpClient<IWellOperationClient>();
|
||||||
|
var rep = factory.Get
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Успешное добавление операции с предварительной очисткой
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[Fact]
|
||||||
|
public async Task InsertRangeWithDeleteBefore_returns_success()
|
||||||
|
{
|
||||||
|
////arrange
|
||||||
|
//dbContext.WellOperations.Add(wellOperation);
|
||||||
|
//dbContext.SaveChanges();
|
||||||
|
|
||||||
|
//var request = new OperationStatRequest
|
||||||
|
//{
|
||||||
|
// DateStartUTC = schedule.DrillStart.DateTime,
|
||||||
|
// DateEndUTC = schedule.DrillEnd.DateTime,
|
||||||
|
// DurationMinutesMin = 0,
|
||||||
|
// DurationMinutesMax = 5
|
||||||
|
//};
|
||||||
|
|
||||||
|
//var dtoExpected = new SlipsStatDto
|
||||||
|
//{
|
||||||
|
// DrillerName = $"{Data.Defaults.Drillers[0].Surname} {Data.Defaults.Drillers[0].Name} {Data.Defaults.Drillers[0].Patronymic}",
|
||||||
|
// WellCount = 1,
|
||||||
|
// SectionCaption = "Пилотный ствол",
|
||||||
|
// SlipsCount = 1,
|
||||||
|
// SlipsTimeInMinutes = (detectedOperation.DateEnd - detectedOperation.DateStart).TotalMinutes,
|
||||||
|
// SectionDepth = factWellOperation.DepthEnd - factWellOperation.DepthStart,
|
||||||
|
//};
|
||||||
|
|
||||||
|
////act
|
||||||
|
//var response = await slipsTimeClient.GetAll(request);
|
||||||
|
|
||||||
|
////assert
|
||||||
|
//Assert.NotNull(response.Content);
|
||||||
|
//Assert.Single(response.Content);
|
||||||
|
|
||||||
|
//var dtoActual = response.Content.First();
|
||||||
|
//MatchHelper.Match(dtoExpected, dtoActual);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Успешное добавление операции без очистки
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[Fact]
|
||||||
|
public async Task InsertRange_returns_success() {
|
||||||
|
//arrange
|
||||||
|
var dbset = dbContext.Set<WellOperation>();
|
||||||
|
dbset.RemoveRange(dbset);
|
||||||
|
dbContext.SaveChanges();
|
||||||
|
|
||||||
|
operationRepository.Validate(dtos);
|
||||||
|
|
||||||
|
//act
|
||||||
|
var response = await wellOperationClient.InsertRange(idWell, dtos);
|
||||||
|
|
||||||
|
//assert
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Неуспешное добавление операции с предварительной очисткой
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[Fact]
|
||||||
|
public async Task InsertRangeWithDeleteBefore_returns_error()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Неуспешное добавление операции без очистки
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[Fact]
|
||||||
|
public async Task InsertRange_returns_error()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -237,7 +237,8 @@ namespace AsbCloudWebApi.Controllers
|
|||||||
wellOperation.IdUser = User.GetUserId();
|
wellOperation.IdUser = User.GetUserId();
|
||||||
wellOperation.IdType = idType;
|
wellOperation.IdType = idType;
|
||||||
|
|
||||||
if (!await operationRepository.ValidateWithDbAsync(new[] { wellOperation }, cancellationToken))
|
var validationResult = operationRepository.ValidateWithDbAsync(new[] { wellOperation }, cancellationToken);
|
||||||
|
if(validationResult.Any())
|
||||||
return this.ValidationBadRequest(nameof(wellOperation), "The date difference between the operations is more than 3 months");
|
return this.ValidationBadRequest(nameof(wellOperation), "The date difference between the operations is more than 3 months");
|
||||||
|
|
||||||
var result = await operationRepository.InsertRangeAsync(new[] { wellOperation }, cancellationToken);
|
var result = await operationRepository.InsertRangeAsync(new[] { wellOperation }, cancellationToken);
|
||||||
@ -291,7 +292,8 @@ namespace AsbCloudWebApi.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!await Validate(wellOperations, deleteBeforeInsert, cancellationToken))
|
var validationResult = Validate(wellOperations, deleteBeforeInsert, cancellationToken);
|
||||||
|
if (validationResult.Any())
|
||||||
return this.ValidationBadRequest(nameof(wellOperations), "The date difference between the operations is more than 3 months");
|
return this.ValidationBadRequest(nameof(wellOperations), "The date difference between the operations is more than 3 months");
|
||||||
|
|
||||||
var result = await operationRepository.InsertRangeAsync(wellOperations, cancellationToken);
|
var result = await operationRepository.InsertRangeAsync(wellOperations, cancellationToken);
|
||||||
@ -307,12 +309,12 @@ namespace AsbCloudWebApi.Controllers
|
|||||||
/// <param name="deleteBeforeInsert"></param>
|
/// <param name="deleteBeforeInsert"></param>
|
||||||
/// <param name="cancellationToken"></param>
|
/// <param name="cancellationToken"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private async Task<bool> Validate(IEnumerable<WellOperationDto> wellOperations, bool deleteBeforeInsert, CancellationToken cancellationToken)
|
private IEnumerable<ValidationResult> Validate(IEnumerable<WellOperationDto> wellOperations, bool deleteBeforeInsert, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (deleteBeforeInsert)
|
if (deleteBeforeInsert)
|
||||||
return operationRepository.Validate(wellOperations);
|
return operationRepository.Validate(wellOperations);
|
||||||
else
|
else
|
||||||
return await operationRepository.ValidateWithDbAsync(wellOperations, cancellationToken);
|
return operationRepository.ValidateWithDbAsync(wellOperations, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -340,7 +342,8 @@ namespace AsbCloudWebApi.Controllers
|
|||||||
value.LastUpdateDate = DateTimeOffset.UtcNow;
|
value.LastUpdateDate = DateTimeOffset.UtcNow;
|
||||||
value.IdUser = User.GetUserId();
|
value.IdUser = User.GetUserId();
|
||||||
|
|
||||||
if (!await operationRepository.ValidateWithDbAsync(new[] { value }, token))
|
var validationResult = operationRepository.ValidateWithDbAsync(new[] { value }, token);
|
||||||
|
if (validationResult.Any())
|
||||||
return this.ValidationBadRequest(nameof(value), "The date difference between the operations is more than 3 months");
|
return this.ValidationBadRequest(nameof(value), "The date difference between the operations is more than 3 months");
|
||||||
|
|
||||||
var result = await operationRepository.UpdateAsync(value, token)
|
var result = await operationRepository.UpdateAsync(value, token)
|
||||||
|
Loading…
Reference in New Issue
Block a user