Валидация данных wellOperation перед вставкой, удалением, импортом...

This commit is contained in:
Olga Nemt 2024-01-24 09:21:07 +05:00
parent 38cbbe4109
commit 6738a30592
3 changed files with 125 additions and 31 deletions

View File

@ -114,5 +114,20 @@ namespace AsbCloudApp.Repositories
/// <param name="cancellationToken"></param> /// <param name="cancellationToken"></param>
/// <returns></returns> /// <returns></returns>
Task<DatesRangeDto?> GetDatesRangeAsync(int idWell, int idType, CancellationToken cancellationToken); Task<DatesRangeDto?> GetDatesRangeAsync(int idWell, int idType, CancellationToken cancellationToken);
}
/// <summary>
/// Валидация данных
/// </summary>
/// <param name="wellOperations"></param>
/// <returns></returns>
bool Validate(IEnumerable<WellOperationDto> wellOperations);
/// <summary>
/// Валидация данных (проверка с базой)
/// </summary>
/// <param name="wellOperations"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<bool> ValidateWithDbAsync(IEnumerable<WellOperationDto> wellOperations, CancellationToken cancellationToken);
}
} }

View File

@ -50,7 +50,7 @@ public class WellOperationRepository : IWellOperationRepository
} }
var result = categories var result = categories
.OrderBy(o => o.Name) .OrderBy(o => o.Name)
.Adapt<IEnumerable<WellOperationCategoryDto>>(); .Adapt<IEnumerable<WellOperationCategoryDto>>();
return result; return result;
@ -89,14 +89,14 @@ public class WellOperationRepository : IWellOperationRepository
} }
private async Task<DateTime?> GetDateLastAssosiatedPlanOperationAsync( private async Task<DateTime?> GetDateLastAssosiatedPlanOperationAsync(
int idWell, int idWell,
DateTime? lessThenDate, DateTime? lessThenDate,
double timeZoneHours, double timeZoneHours,
CancellationToken token) CancellationToken token)
{ {
if (lessThenDate is null) if (lessThenDate is null)
return null; return null;
var currentDateOffset = lessThenDate.Value.ToUtcDateTimeOffset(timeZoneHours); var currentDateOffset = lessThenDate.Value.ToUtcDateTimeOffset(timeZoneHours);
var timeZoneOffset = TimeSpan.FromHours(timeZoneHours); var timeZoneOffset = TimeSpan.FromHours(timeZoneHours);
@ -187,7 +187,7 @@ public class WellOperationRepository : IWellOperationRepository
public async Task<DatesRangeDto?> GetDatesRangeAsync(int idWell, int idType, CancellationToken cancellationToken) public async Task<DatesRangeDto?> GetDatesRangeAsync(int idWell, int idType, CancellationToken cancellationToken)
{ {
var timezone = wellService.GetTimezone(idWell); var timezone = wellService.GetTimezone(idWell);
var query = db.WellOperations.Where(o => o.IdWell == idWell && o.IdType == idType); var query = db.WellOperations.Where(o => o.IdWell == idWell && o.IdType == idType);
if (!await query.AnyAsync(cancellationToken)) if (!await query.AnyAsync(cancellationToken))
@ -195,7 +195,7 @@ public class WellOperationRepository : IWellOperationRepository
var minDate = await query.MinAsync(o => o.DateStart, cancellationToken); var minDate = await query.MinAsync(o => o.DateStart, cancellationToken);
var maxDate = await query.MaxAsync(o => o.DateStart, cancellationToken); var maxDate = await query.MaxAsync(o => o.DateStart, cancellationToken);
return new DatesRangeDto return new DatesRangeDto
{ {
From = minDate.ToRemoteDateTime(timezone.Hours), From = minDate.ToRemoteDateTime(timezone.Hours),
@ -306,12 +306,13 @@ public class WellOperationRepository : IWellOperationRepository
DeltaDepth = g.Sum(o => o.DurationDepth), DeltaDepth = g.Sum(o => o.DurationDepth),
IdParent = parentRelationDictionary[g.Key].IdParent IdParent = parentRelationDictionary[g.Key].IdParent
}); });
while (dtos.All(x => x.IdParent != null)) while (dtos.All(x => x.IdParent != null))
{ {
dtos = dtos dtos = dtos
.GroupBy(o => o.IdParent!) .GroupBy(o => o.IdParent!)
.Select(g => { .Select(g =>
{
var idCategory = g.Key ?? int.MinValue; var idCategory = g.Key ?? int.MinValue;
var category = parentRelationDictionary.GetValueOrDefault(idCategory); var category = parentRelationDictionary.GetValueOrDefault(idCategory);
var newDto = new WellGroupOpertionDto var newDto = new WellGroupOpertionDto
@ -330,6 +331,58 @@ public class WellOperationRepository : IWellOperationRepository
return dtos; return dtos;
} }
public async Task<bool> ValidateWithDbAsync(IEnumerable<WellOperationDto> wellOperationDtos, CancellationToken token)
{
var firstOperation = wellOperationDtos
.FirstOrDefault();
if (firstOperation is null)
return false;
var request = new WellOperationRequest()
{
IdWell = firstOperation.IdWell,
OperationType = firstOperation.IdType,
};
var operationWithMaxDateStart = await BuildQuery(request)
.OrderByDescending(o => o.DateStart)
.FirstOrDefaultAsync(token);
if (operationWithMaxDateStart is null)
return Validate(wellOperationDtos);
var maxOperationDateStart = operationWithMaxDateStart.DateStart;
foreach (var dto in wellOperationDtos)
{
var currentOperationDateStart = dto.DateStart.ToUniversalTime();
if (maxOperationDateStart!.AddMonths(3) < currentOperationDateStart)
return false;
maxOperationDateStart = currentOperationDateStart;
}
return true;
}
public bool Validate(IEnumerable<WellOperationDto> wellOperationDtos)
{
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.AddMonths(3) < currentOperationDateStart)
return false;
maxOperationDateStart = currentOperationDateStart;
}
return true;
}
/// <inheritdoc/> /// <inheritdoc/>
public async Task<int> InsertRangeAsync( public async Task<int> InsertRangeAsync(
IEnumerable<WellOperationDto> wellOperationDtos, IEnumerable<WellOperationDto> wellOperationDtos,

View File

@ -1,7 +1,13 @@
using AsbCloudApp.Data; using AsbCloudApp.Data;
using AsbCloudApp.Data.WellOperationImport;
using AsbCloudApp.Data.WellOperationImport.Options;
using AsbCloudApp.Exceptions;
using AsbCloudApp.Repositories; using AsbCloudApp.Repositories;
using AsbCloudApp.Requests; using AsbCloudApp.Requests;
using AsbCloudApp.Services; using AsbCloudApp.Services;
using AsbCloudApp.Services.WellOperationImport;
using AsbCloudDb.Model;
using AsbCloudInfrastructure;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
@ -12,12 +18,6 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using AsbCloudApp.Data.WellOperationImport;
using AsbCloudApp.Services.WellOperationImport;
using AsbCloudApp.Data.WellOperationImport.Options;
using AsbCloudApp.Exceptions;
using AsbCloudDb.Model;
using AsbCloudInfrastructure;
namespace AsbCloudWebApi.Controllers namespace AsbCloudWebApi.Controllers
{ {
@ -39,8 +39,8 @@ namespace AsbCloudWebApi.Controllers
private readonly IWellOperationExcelParser<WellOperationImportGazpromKhantosOptionsDto> wellOperationGazpromKhantosExcelParser; private readonly IWellOperationExcelParser<WellOperationImportGazpromKhantosOptionsDto> wellOperationGazpromKhantosExcelParser;
private readonly IUserRepository userRepository; private readonly IUserRepository userRepository;
public WellOperationController(IWellOperationRepository operationRepository, public WellOperationController(IWellOperationRepository operationRepository,
IWellService wellService, IWellService wellService,
IWellOperationImportTemplateService wellOperationImportTemplateService, IWellOperationImportTemplateService wellOperationImportTemplateService,
IWellOperationExportService wellOperationExportService, IWellOperationExportService wellOperationExportService,
IWellOperationImportService wellOperationImportService, IWellOperationImportService wellOperationImportService,
@ -231,12 +231,15 @@ namespace AsbCloudWebApi.Controllers
if (!await CanUserEditWellOperationsAsync(idWell, cancellationToken)) if (!await CanUserEditWellOperationsAsync(idWell, cancellationToken))
return Forbid(); return Forbid();
wellOperation.IdWell = idWell; wellOperation.IdWell = idWell;
wellOperation.LastUpdateDate = DateTimeOffset.UtcNow; wellOperation.LastUpdateDate = DateTimeOffset.UtcNow;
wellOperation.IdUser = User.GetUserId(); wellOperation.IdUser = User.GetUserId();
wellOperation.IdType = idType; wellOperation.IdType = idType;
if (!await operationRepository.ValidateWithDbAsync(new[] { wellOperation }, cancellationToken))
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);
return Ok(result); return Ok(result);
@ -278,7 +281,7 @@ namespace AsbCloudWebApi.Controllers
await operationRepository.DeleteAsync(existingOperations.Select(o => o.Id), cancellationToken); await operationRepository.DeleteAsync(existingOperations.Select(o => o.Id), cancellationToken);
} }
foreach (var wellOperation in wellOperations) foreach (var wellOperation in wellOperations)
{ {
wellOperation.IdWell = idWell; wellOperation.IdWell = idWell;
@ -287,11 +290,31 @@ namespace AsbCloudWebApi.Controllers
wellOperation.IdType = idType; wellOperation.IdType = idType;
} }
if (!await Validate(wellOperations, deleteBeforeInsert, cancellationToken))
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);
return Ok(result); return Ok(result);
} }
/// <summary>
/// Валидация данных перед вставкой / обновлением / импортом
/// </summary>
/// <param name="wellOperations"></param>
/// <param name="deleteBeforeInsert"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
private async Task<bool> Validate(IEnumerable<WellOperationDto> wellOperations, bool deleteBeforeInsert, CancellationToken cancellationToken)
{
if (deleteBeforeInsert)
return operationRepository.Validate(wellOperations);
else
return await operationRepository.ValidateWithDbAsync(wellOperations, cancellationToken);
}
/// <summary> /// <summary>
/// Обновляет выбранную операцию на скважине /// Обновляет выбранную операцию на скважине
/// </summary> /// </summary>
@ -308,7 +331,7 @@ namespace AsbCloudWebApi.Controllers
{ {
if (!await CanUserAccessToWellAsync(idWell, token)) if (!await CanUserAccessToWellAsync(idWell, token))
return Forbid(); return Forbid();
if (!await CanUserEditWellOperationsAsync(idWell, token)) if (!await CanUserEditWellOperationsAsync(idWell, token))
return Forbid(); return Forbid();
@ -317,6 +340,9 @@ 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))
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)
.ConfigureAwait(false); .ConfigureAwait(false);
return Ok(result); return Ok(result);
@ -336,7 +362,7 @@ namespace AsbCloudWebApi.Controllers
{ {
if (!await CanUserAccessToWellAsync(idWell, token)) if (!await CanUserAccessToWellAsync(idWell, token))
return Forbid(); return Forbid();
if (!await CanUserEditWellOperationsAsync(idWell, token)) if (!await CanUserEditWellOperationsAsync(idWell, token))
return Forbid(); return Forbid();
@ -373,7 +399,7 @@ namespace AsbCloudWebApi.Controllers
deleteBeforeInsert, deleteBeforeInsert,
cancellationToken); cancellationToken);
} }
/// <summary> /// <summary>
/// Импорт плановых операций из excel (xlsx) файла. Стандартный заполненный шаблон /// Импорт плановых операций из excel (xlsx) файла. Стандартный заполненный шаблон
/// </summary> /// </summary>
@ -393,7 +419,7 @@ namespace AsbCloudWebApi.Controllers
{ {
IdType = WellOperation.IdOperationTypePlan IdType = WellOperation.IdOperationTypePlan
}; };
return ImportExcelFileAsync(idWell, files, options, return ImportExcelFileAsync(idWell, files, options,
(stream, _) => wellOperationDefaultExcelParser.Parse(stream, options), (stream, _) => wellOperationDefaultExcelParser.Parse(stream, options),
null, null,
@ -522,7 +548,7 @@ namespace AsbCloudWebApi.Controllers
return this.ValidationBadRequest(nameof(files), "Требуется xlsx файл."); return this.ValidationBadRequest(nameof(files), "Требуется xlsx файл.");
using Stream stream = file.OpenReadStream(); using Stream stream = file.OpenReadStream();
try try
{ {
var sheet = parseMethod(stream, options); var sheet = parseMethod(stream, options);
@ -541,8 +567,8 @@ namespace AsbCloudWebApi.Controllers
//TODO: очень быстрый костыль //TODO: очень быстрый костыль
if (deleteBeforeInsert is not null && options.IdType == WellOperation.IdOperationTypeFact) if (deleteBeforeInsert is not null && options.IdType == WellOperation.IdOperationTypeFact)
{ {
return await InsertRangeAsync(idWell, options.IdType, return await InsertRangeAsync(idWell, options.IdType,
deleteBeforeInsert.Value, deleteBeforeInsert.Value,
wellOperations, wellOperations,
cancellationToken); cancellationToken);
} }
@ -554,21 +580,21 @@ namespace AsbCloudWebApi.Controllers
return this.ValidationBadRequest(nameof(files), ex.Message); return this.ValidationBadRequest(nameof(files), ex.Message);
} }
} }
private async Task<bool> CanUserAccessToWellAsync(int idWell, CancellationToken token) private async Task<bool> CanUserAccessToWellAsync(int idWell, CancellationToken token)
{ {
int? idCompany = User.GetCompanyId(); int? idCompany = User.GetCompanyId();
return idCompany is not null && await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, return idCompany is not null && await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
idWell, token).ConfigureAwait(false); idWell, token).ConfigureAwait(false);
} }
private async Task<bool> CanUserEditWellOperationsAsync(int idWell, CancellationToken token) private async Task<bool> CanUserEditWellOperationsAsync(int idWell, CancellationToken token)
{ {
var idUser = User.GetUserId(); var idUser = User.GetUserId();
if (!idUser.HasValue) if (!idUser.HasValue)
return false; return false;
var well = await wellService.GetOrDefaultAsync(idWell, token); var well = await wellService.GetOrDefaultAsync(idWell, token);
if (well is null) if (well is null)