From 672f78fca99461b65b5f25de51a5efe0644e8d52 Mon Sep 17 00:00:00 2001 From: ngfrolov Date: Thu, 25 Jan 2024 16:47:04 +0500 Subject: [PATCH] WellOperationRepository refactor ValidateWithDbAsync and Validate --- .../Repositories/IWellOperationRepository.cs | 2 +- .../Repository/WellOperationRepository.cs | 48 ++++++++++--------- .../Controllers/WellOperationController.cs | 12 ++--- AsbCloudWebApi/Extentions.cs | 24 ++++++++++ 4 files changed, 56 insertions(+), 30 deletions(-) diff --git a/AsbCloudApp/Repositories/IWellOperationRepository.cs b/AsbCloudApp/Repositories/IWellOperationRepository.cs index 43a7a568..8cb313ac 100644 --- a/AsbCloudApp/Repositories/IWellOperationRepository.cs +++ b/AsbCloudApp/Repositories/IWellOperationRepository.cs @@ -129,6 +129,6 @@ namespace AsbCloudApp.Repositories /// /// /// - IEnumerable ValidateWithDbAsync(IEnumerable wellOperations, CancellationToken cancellationToken); + Task> ValidateWithDbAsync(IEnumerable wellOperations, CancellationToken cancellationToken); } } \ No newline at end of file diff --git a/AsbCloudInfrastructure/Repository/WellOperationRepository.cs b/AsbCloudInfrastructure/Repository/WellOperationRepository.cs index 2e4e956a..208e94ac 100644 --- a/AsbCloudInfrastructure/Repository/WellOperationRepository.cs +++ b/AsbCloudInfrastructure/Repository/WellOperationRepository.cs @@ -334,12 +334,13 @@ public class WellOperationRepository : IWellOperationRepository return dtos; } - public IEnumerable ValidateWithDbAsync(IEnumerable wellOperationDtos, CancellationToken token) + public async Task> ValidateWithDbAsync(IEnumerable wellOperationDtos, CancellationToken token) { var firstOperation = wellOperationDtos .FirstOrDefault(); + if (firstOperation is null) - yield break; + return Enumerable.Empty(); var request = new WellOperationRequest() { @@ -347,48 +348,49 @@ public class WellOperationRepository : IWellOperationRepository OperationType = firstOperation.IdType, }; - var entities = BuildQuery(request) + var entities = await BuildQuery(request) .AsNoTracking() - .ToArray(); + .ToArrayAsync(token); var wellOperationsUnion = entities.Union(wellOperationDtos).OrderBy(o => o.DateStart); var results = Validate(wellOperationsUnion); - foreach ( var result in results) - yield return result; + return results; } public IEnumerable Validate(IEnumerable wellOperationDtos) { - var firstOperation = wellOperationDtos - .FirstOrDefault(); - if (firstOperation is null) + var enumerator = wellOperationDtos.OrderBy(o => o.DateStart) + .GetEnumerator(); + + if (!enumerator.MoveNext()) yield break; - var wellOperations = wellOperationDtos.OrderBy(o => o.DateStart).ToArray(); - for (var i = 1; i < wellOperations.Length; i++) + var previous = enumerator.Current; + + while(enumerator.MoveNext()) { - var prevOperation = wellOperations[i - 1]; - var currentOperation = wellOperations[i]; + var current = enumerator.Current; + var previousDateStart = previous.DateStart.ToUniversalTime(); + var currentDateStart = current.DateStart.ToUniversalTime(); - var prevOperationDateStart = prevOperation.DateStart.ToUniversalTime(); - var currentOperationDateStart = currentOperation.DateStart.ToUniversalTime(); + var previousDateEnd = previous.DateStart.AddHours(previous.DurationHours).ToUniversalTime(); - var prevOperationDateEnd = prevOperation.DateStart.AddHours(prevOperation.DurationHours).ToUniversalTime(); - - if (prevOperationDateStart.AddDays(Gap) < currentOperationDateStart) + if (previousDateStart.AddDays(Gap) < currentDateStart) { yield return new ValidationResult( - $"Разница дат между операциями не должна превышать 90 дней", - new[] { nameof(wellOperations) }); + "Разница дат между операциями не должна превышать 90 дней", + new[] { nameof(wellOperationDtos) }); } - if (prevOperationDateEnd > currentOperationDateStart) + if (previousDateEnd > currentDateStart) { yield return new ValidationResult( - $"Предыдущая операция не завершена", - new[] { nameof(wellOperations) }); + "Предыдущая операция не завершена", + new[] { nameof(wellOperationDtos) }); } + + previous = current; } } diff --git a/AsbCloudWebApi/Controllers/WellOperationController.cs b/AsbCloudWebApi/Controllers/WellOperationController.cs index 5c0039cc..79c7d900 100644 --- a/AsbCloudWebApi/Controllers/WellOperationController.cs +++ b/AsbCloudWebApi/Controllers/WellOperationController.cs @@ -237,9 +237,9 @@ namespace AsbCloudWebApi.Controllers wellOperation.IdUser = User.GetUserId(); wellOperation.IdType = idType; - var validationResult = operationRepository.ValidateWithDbAsync(new[] { wellOperation }, cancellationToken); + var validationResult = awaitoperationRepository.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(validationResult); var result = await operationRepository.InsertRangeAsync(new[] { wellOperation }, cancellationToken); @@ -294,7 +294,7 @@ namespace AsbCloudWebApi.Controllers 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(validationResult); var result = await operationRepository.InsertRangeAsync(wellOperations, cancellationToken); @@ -314,7 +314,7 @@ namespace AsbCloudWebApi.Controllers if (deleteBeforeInsert) return operationRepository.Validate(wellOperations); else - return operationRepository.ValidateWithDbAsync(wellOperations, cancellationToken); + return await operationRepository.ValidateWithDbAsync(wellOperations, cancellationToken); } /// @@ -342,9 +342,9 @@ namespace AsbCloudWebApi.Controllers value.LastUpdateDate = DateTimeOffset.UtcNow; value.IdUser = User.GetUserId(); - var validationResult = operationRepository.ValidateWithDbAsync(new[] { value }, token); + var validationResult = await 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(validationResult); var result = await operationRepository.UpdateAsync(value, token) .ConfigureAwait(false); diff --git a/AsbCloudWebApi/Extentions.cs b/AsbCloudWebApi/Extentions.cs index ba87612f..c064d2de 100644 --- a/AsbCloudWebApi/Extentions.cs +++ b/AsbCloudWebApi/Extentions.cs @@ -3,6 +3,8 @@ using AsbCloudWebApi.Converters; using System; using System.Collections.Generic; using System.ComponentModel; +using System.ComponentModel.DataAnnotations; +using System.Linq; using System.Security.Claims; namespace Microsoft.AspNetCore.Mvc @@ -53,6 +55,28 @@ namespace Microsoft.AspNetCore.Mvc return controller.BadRequest(problem); } + /// + /// + /// Returns BadRequest with ValidationProblemDetails as body + /// + /// + /// Используйте этот метод только если валидацию нельзя сделать через + /// атрибуты валидации или IValidatableObject модели. + /// + /// + /// + /// + /// + /// + public static BadRequestObjectResult ValidationBadRequest(this ControllerBase controller, IEnumerable 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) { TypeDescriptor.AddAttributes(typeof(DateOnly), new TypeConverterAttribute(typeof(DateOnlyTypeConverter)));