diff --git a/AsbCloudApp/Repositories/IWellOperationRepository.cs b/AsbCloudApp/Repositories/IWellOperationRepository.cs
index d1db155e..d6302726 100644
--- a/AsbCloudApp/Repositories/IWellOperationRepository.cs
+++ b/AsbCloudApp/Repositories/IWellOperationRepository.cs
@@ -114,5 +114,20 @@ namespace AsbCloudApp.Repositories
///
///
Task GetDatesRangeAsync(int idWell, int idType, CancellationToken cancellationToken);
- }
+
+ ///
+ /// Валидация данных
+ ///
+ ///
+ ///
+ bool Validate(IEnumerable wellOperations);
+
+ ///
+ /// Валидация данных (проверка с базой)
+ ///
+ ///
+ ///
+ ///
+ 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 fb0a8c12..ba566bca 100644
--- a/AsbCloudInfrastructure/Repository/WellOperationRepository.cs
+++ b/AsbCloudInfrastructure/Repository/WellOperationRepository.cs
@@ -50,7 +50,7 @@ public class WellOperationRepository : IWellOperationRepository
}
var result = categories
- .OrderBy(o => o.Name)
+ .OrderBy(o => o.Name)
.Adapt>();
return result;
@@ -89,14 +89,14 @@ public class WellOperationRepository : IWellOperationRepository
}
private async Task GetDateLastAssosiatedPlanOperationAsync(
- int idWell,
- DateTime? lessThenDate,
- double timeZoneHours,
+ int idWell,
+ DateTime? lessThenDate,
+ double timeZoneHours,
CancellationToken token)
{
- if (lessThenDate is null)
+ if (lessThenDate is null)
return null;
-
+
var currentDateOffset = lessThenDate.Value.ToUtcDateTimeOffset(timeZoneHours);
var timeZoneOffset = TimeSpan.FromHours(timeZoneHours);
@@ -187,7 +187,7 @@ public class WellOperationRepository : IWellOperationRepository
public async Task GetDatesRangeAsync(int idWell, int idType, CancellationToken cancellationToken)
{
var timezone = wellService.GetTimezone(idWell);
-
+
var query = db.WellOperations.Where(o => o.IdWell == idWell && o.IdType == idType);
if (!await query.AnyAsync(cancellationToken))
@@ -195,7 +195,7 @@ public class WellOperationRepository : IWellOperationRepository
var minDate = await query.MinAsync(o => o.DateStart, cancellationToken);
var maxDate = await query.MaxAsync(o => o.DateStart, cancellationToken);
-
+
return new DatesRangeDto
{
From = minDate.ToRemoteDateTime(timezone.Hours),
@@ -306,12 +306,13 @@ public class WellOperationRepository : IWellOperationRepository
DeltaDepth = g.Sum(o => o.DurationDepth),
IdParent = parentRelationDictionary[g.Key].IdParent
});
-
+
while (dtos.All(x => x.IdParent != null))
{
dtos = dtos
.GroupBy(o => o.IdParent!)
- .Select(g => {
+ .Select(g =>
+ {
var idCategory = g.Key ?? int.MinValue;
var category = parentRelationDictionary.GetValueOrDefault(idCategory);
var newDto = new WellGroupOpertionDto
@@ -330,6 +331,58 @@ public class WellOperationRepository : IWellOperationRepository
return dtos;
}
+ public async Task ValidateWithDbAsync(IEnumerable 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 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;
+ }
+
///
public async Task InsertRangeAsync(
IEnumerable wellOperationDtos,
diff --git a/AsbCloudWebApi/Controllers/WellOperationController.cs b/AsbCloudWebApi/Controllers/WellOperationController.cs
index ae0c8b92..fa479f12 100644
--- a/AsbCloudWebApi/Controllers/WellOperationController.cs
+++ b/AsbCloudWebApi/Controllers/WellOperationController.cs
@@ -1,7 +1,13 @@
using AsbCloudApp.Data;
+using AsbCloudApp.Data.WellOperationImport;
+using AsbCloudApp.Data.WellOperationImport.Options;
+using AsbCloudApp.Exceptions;
using AsbCloudApp.Repositories;
using AsbCloudApp.Requests;
using AsbCloudApp.Services;
+using AsbCloudApp.Services.WellOperationImport;
+using AsbCloudDb.Model;
+using AsbCloudInfrastructure;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
@@ -12,12 +18,6 @@ using System.IO;
using System.Linq;
using System.Threading;
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
{
@@ -39,8 +39,8 @@ namespace AsbCloudWebApi.Controllers
private readonly IWellOperationExcelParser wellOperationGazpromKhantosExcelParser;
private readonly IUserRepository userRepository;
- public WellOperationController(IWellOperationRepository operationRepository,
- IWellService wellService,
+ public WellOperationController(IWellOperationRepository operationRepository,
+ IWellService wellService,
IWellOperationImportTemplateService wellOperationImportTemplateService,
IWellOperationExportService wellOperationExportService,
IWellOperationImportService wellOperationImportService,
@@ -231,12 +231,15 @@ namespace AsbCloudWebApi.Controllers
if (!await CanUserEditWellOperationsAsync(idWell, cancellationToken))
return Forbid();
-
+
wellOperation.IdWell = idWell;
wellOperation.LastUpdateDate = DateTimeOffset.UtcNow;
wellOperation.IdUser = User.GetUserId();
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);
return Ok(result);
@@ -278,7 +281,7 @@ namespace AsbCloudWebApi.Controllers
await operationRepository.DeleteAsync(existingOperations.Select(o => o.Id), cancellationToken);
}
-
+
foreach (var wellOperation in wellOperations)
{
wellOperation.IdWell = idWell;
@@ -287,11 +290,31 @@ namespace AsbCloudWebApi.Controllers
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);
return Ok(result);
}
+
+ ///
+ /// Валидация данных перед вставкой / обновлением / импортом
+ ///
+ ///
+ ///
+ ///
+ ///
+ private async Task Validate(IEnumerable wellOperations, bool deleteBeforeInsert, CancellationToken cancellationToken)
+ {
+ if (deleteBeforeInsert)
+ return operationRepository.Validate(wellOperations);
+ else
+ return await operationRepository.ValidateWithDbAsync(wellOperations, cancellationToken);
+ }
+
///
/// Обновляет выбранную операцию на скважине
///
@@ -308,7 +331,7 @@ namespace AsbCloudWebApi.Controllers
{
if (!await CanUserAccessToWellAsync(idWell, token))
return Forbid();
-
+
if (!await CanUserEditWellOperationsAsync(idWell, token))
return Forbid();
@@ -317,6 +340,9 @@ namespace AsbCloudWebApi.Controllers
value.LastUpdateDate = DateTimeOffset.UtcNow;
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)
.ConfigureAwait(false);
return Ok(result);
@@ -336,7 +362,7 @@ namespace AsbCloudWebApi.Controllers
{
if (!await CanUserAccessToWellAsync(idWell, token))
return Forbid();
-
+
if (!await CanUserEditWellOperationsAsync(idWell, token))
return Forbid();
@@ -373,7 +399,7 @@ namespace AsbCloudWebApi.Controllers
deleteBeforeInsert,
cancellationToken);
}
-
+
///
/// Импорт плановых операций из excel (xlsx) файла. Стандартный заполненный шаблон
///
@@ -393,7 +419,7 @@ namespace AsbCloudWebApi.Controllers
{
IdType = WellOperation.IdOperationTypePlan
};
-
+
return ImportExcelFileAsync(idWell, files, options,
(stream, _) => wellOperationDefaultExcelParser.Parse(stream, options),
null,
@@ -522,7 +548,7 @@ namespace AsbCloudWebApi.Controllers
return this.ValidationBadRequest(nameof(files), "Требуется xlsx файл.");
using Stream stream = file.OpenReadStream();
-
+
try
{
var sheet = parseMethod(stream, options);
@@ -541,8 +567,8 @@ namespace AsbCloudWebApi.Controllers
//TODO: очень быстрый костыль
if (deleteBeforeInsert is not null && options.IdType == WellOperation.IdOperationTypeFact)
{
- return await InsertRangeAsync(idWell, options.IdType,
- deleteBeforeInsert.Value,
+ return await InsertRangeAsync(idWell, options.IdType,
+ deleteBeforeInsert.Value,
wellOperations,
cancellationToken);
}
@@ -554,21 +580,21 @@ namespace AsbCloudWebApi.Controllers
return this.ValidationBadRequest(nameof(files), ex.Message);
}
}
-
+
private async Task CanUserAccessToWellAsync(int idWell, CancellationToken token)
{
int? idCompany = User.GetCompanyId();
return idCompany is not null && await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
idWell, token).ConfigureAwait(false);
}
-
+
private async Task CanUserEditWellOperationsAsync(int idWell, CancellationToken token)
{
var idUser = User.GetUserId();
if (!idUser.HasValue)
return false;
-
+
var well = await wellService.GetOrDefaultAsync(idWell, token);
if (well is null)