WellOperationRepository refactor ValidateWithDbAsync and Validate

This commit is contained in:
ngfrolov 2024-01-25 16:47:04 +05:00
parent a8e2ea9632
commit 672f78fca9
Signed by untrusted user who does not match committer: ng.frolov
GPG Key ID: E99907A0357B29A7
4 changed files with 56 additions and 30 deletions

View File

@ -129,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>
IEnumerable<ValidationResult> ValidateWithDbAsync(IEnumerable<WellOperationDto> wellOperations, CancellationToken cancellationToken); Task<IEnumerable<ValidationResult>> ValidateWithDbAsync(IEnumerable<WellOperationDto> wellOperations, CancellationToken cancellationToken);
} }
} }

View File

@ -334,12 +334,13 @@ public class WellOperationRepository : IWellOperationRepository
return dtos; return dtos;
} }
public IEnumerable<ValidationResult> ValidateWithDbAsync(IEnumerable<WellOperationDto> wellOperationDtos, CancellationToken token) public async Task<IEnumerable<ValidationResult>> ValidateWithDbAsync(IEnumerable<WellOperationDto> wellOperationDtos, CancellationToken token)
{ {
var firstOperation = wellOperationDtos var firstOperation = wellOperationDtos
.FirstOrDefault(); .FirstOrDefault();
if (firstOperation is null) if (firstOperation is null)
yield break; return Enumerable.Empty<ValidationResult>();
var request = new WellOperationRequest() var request = new WellOperationRequest()
{ {
@ -347,48 +348,49 @@ public class WellOperationRepository : IWellOperationRepository
OperationType = firstOperation.IdType, OperationType = firstOperation.IdType,
}; };
var entities = BuildQuery(request) var entities = await BuildQuery(request)
.AsNoTracking() .AsNoTracking()
.ToArray(); .ToArrayAsync(token);
var wellOperationsUnion = entities.Union(wellOperationDtos).OrderBy(o => o.DateStart); var wellOperationsUnion = entities.Union(wellOperationDtos).OrderBy(o => o.DateStart);
var results = Validate(wellOperationsUnion); var results = Validate(wellOperationsUnion);
foreach ( var result in results) return results;
yield return result;
} }
public IEnumerable<ValidationResult> Validate(IEnumerable<WellOperationDto> wellOperationDtos) public IEnumerable<ValidationResult> Validate(IEnumerable<WellOperationDto> wellOperationDtos)
{ {
var firstOperation = wellOperationDtos var enumerator = wellOperationDtos.OrderBy(o => o.DateStart)
.FirstOrDefault(); .GetEnumerator();
if (firstOperation is null)
if (!enumerator.MoveNext())
yield break; yield break;
var wellOperations = wellOperationDtos.OrderBy(o => o.DateStart).ToArray(); var previous = enumerator.Current;
for (var i = 1; i < wellOperations.Length; i++)
while(enumerator.MoveNext())
{ {
var prevOperation = wellOperations[i - 1]; var current = enumerator.Current;
var currentOperation = wellOperations[i]; var previousDateStart = previous.DateStart.ToUniversalTime();
var currentDateStart = current.DateStart.ToUniversalTime();
var prevOperationDateStart = prevOperation.DateStart.ToUniversalTime(); var previousDateEnd = previous.DateStart.AddHours(previous.DurationHours).ToUniversalTime();
var currentOperationDateStart = currentOperation.DateStart.ToUniversalTime();
var prevOperationDateEnd = prevOperation.DateStart.AddHours(prevOperation.DurationHours).ToUniversalTime(); if (previousDateStart.AddDays(Gap) < currentDateStart)
if (prevOperationDateStart.AddDays(Gap) < currentOperationDateStart)
{ {
yield return new ValidationResult( yield return new ValidationResult(
$"Разница дат между операциями не должна превышать 90 дней", "Разница дат между операциями не должна превышать 90 дней",
new[] { nameof(wellOperations) }); new[] { nameof(wellOperationDtos) });
} }
if (prevOperationDateEnd > currentOperationDateStart) if (previousDateEnd > currentDateStart)
{ {
yield return new ValidationResult( yield return new ValidationResult(
$"Предыдущая операция не завершена", "Предыдущая операция не завершена",
new[] { nameof(wellOperations) }); new[] { nameof(wellOperationDtos) });
} }
previous = current;
} }
} }

View File

@ -237,9 +237,9 @@ namespace AsbCloudWebApi.Controllers
wellOperation.IdUser = User.GetUserId(); wellOperation.IdUser = User.GetUserId();
wellOperation.IdType = idType; wellOperation.IdType = idType;
var validationResult = operationRepository.ValidateWithDbAsync(new[] { wellOperation }, cancellationToken); var validationResult = awaitoperationRepository.ValidateWithDbAsync(new[] { wellOperation }, cancellationToken);
if(validationResult.Any()) if(validationResult.Any())
return this.ValidationBadRequest(nameof(wellOperation), "The date difference between the operations is more than 3 months"); return this.ValidationBadRequest(validationResult);
var result = await operationRepository.InsertRangeAsync(new[] { wellOperation }, cancellationToken); var result = await operationRepository.InsertRangeAsync(new[] { wellOperation }, cancellationToken);
@ -294,7 +294,7 @@ namespace AsbCloudWebApi.Controllers
var validationResult = Validate(wellOperations, deleteBeforeInsert, cancellationToken); var validationResult = Validate(wellOperations, deleteBeforeInsert, cancellationToken);
if (validationResult.Any()) if (validationResult.Any())
return this.ValidationBadRequest(nameof(wellOperations), "The date difference between the operations is more than 3 months"); return this.ValidationBadRequest(validationResult);
var result = await operationRepository.InsertRangeAsync(wellOperations, cancellationToken); var result = await operationRepository.InsertRangeAsync(wellOperations, cancellationToken);
@ -314,7 +314,7 @@ namespace AsbCloudWebApi.Controllers
if (deleteBeforeInsert) if (deleteBeforeInsert)
return operationRepository.Validate(wellOperations); return operationRepository.Validate(wellOperations);
else else
return operationRepository.ValidateWithDbAsync(wellOperations, cancellationToken); return await operationRepository.ValidateWithDbAsync(wellOperations, cancellationToken);
} }
/// <summary> /// <summary>
@ -342,9 +342,9 @@ namespace AsbCloudWebApi.Controllers
value.LastUpdateDate = DateTimeOffset.UtcNow; value.LastUpdateDate = DateTimeOffset.UtcNow;
value.IdUser = User.GetUserId(); value.IdUser = User.GetUserId();
var validationResult = operationRepository.ValidateWithDbAsync(new[] { value }, token); var validationResult = await operationRepository.ValidateWithDbAsync(new[] { value }, token);
if (validationResult.Any()) if (validationResult.Any())
return this.ValidationBadRequest(nameof(value), "The date difference between the operations is more than 3 months"); return this.ValidationBadRequest(validationResult);
var result = await operationRepository.UpdateAsync(value, token) var result = await operationRepository.UpdateAsync(value, token)
.ConfigureAwait(false); .ConfigureAwait(false);

View File

@ -3,6 +3,8 @@ using AsbCloudWebApi.Converters;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Security.Claims; using System.Security.Claims;
namespace Microsoft.AspNetCore.Mvc namespace Microsoft.AspNetCore.Mvc
@ -53,6 +55,28 @@ namespace Microsoft.AspNetCore.Mvc
return controller.BadRequest(problem); return controller.BadRequest(problem);
} }
/// <summary>
/// <para>
/// Returns BadRequest with ValidationProblemDetails as body
/// </para>
/// <para>
/// Используйте этот метод только если валидацию нельзя сделать через
/// атрибуты валидации или IValidatableObject модели.
/// </para>
/// </summary>
/// <param name="controller"></param>
/// <param name="paramName"></param>
/// <param name="error"></param>
/// <returns></returns>
public static BadRequestObjectResult ValidationBadRequest(this ControllerBase controller, IEnumerable<ValidationResult> validationResults)
{
var errors = validationResults
.SelectMany(e => e.MemberNames.Select(name=> new { name, e.ErrorMessage }))
.ToDictionary(e => e.name, e => new[] { e.ErrorMessage ?? string.Empty });
var problem = new ValidationProblemDetails(errors);
return controller.BadRequest(problem);
}
public static MvcOptions UseDateOnlyTimeOnlyStringConverters(this MvcOptions options) public static MvcOptions UseDateOnlyTimeOnlyStringConverters(this MvcOptions options)
{ {
TypeDescriptor.AddAttributes(typeof(DateOnly), new TypeConverterAttribute(typeof(DateOnlyTypeConverter))); TypeDescriptor.AddAttributes(typeof(DateOnly), new TypeConverterAttribute(typeof(DateOnlyTypeConverter)));