DD.WellWorkover.Cloud/AsbCloudInfrastructure/Services/WellOperationImport/WellOperationImportService.cs

138 lines
5.5 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data;
using AsbCloudApp.Data.WellOperationImport;
using AsbCloudApp.Exceptions;
using AsbCloudApp.Repositories;
using AsbCloudApp.Requests;
using AsbCloudApp.Services.WellOperationImport;
using AsbCloudDb.Model;
using AsbCloudInfrastructure.Services.WellOperationImport.Constants;
namespace AsbCloudInfrastructure.Services.WellOperationImport;
public class WellOperationImportService : IWellOperationImportService
{
private readonly IEnumerable<IWellOperationExcelParser> excelParsers;
private readonly IWellOperationRepository wellOperationRepository;
private static readonly DateTime dateLimitMin = new(2001, 1, 1, 0, 0, 0);
private static readonly DateTime dateLimitMax = new(2099, 1, 1, 0, 0, 0);
private static readonly TimeSpan drillingDurationLimitMax = TimeSpan.FromDays(366);
public WellOperationImportService(IEnumerable<IWellOperationExcelParser> excelParsers,
IWellOperationRepository wellOperationRepository)
{
this.excelParsers = excelParsers;
this.wellOperationRepository = wellOperationRepository;
}
public async Task ImportAsync(int idWell, int idUser, int idType, Stream stream, WellOperationParserOptionsDto options,
bool deleteWellOperationsBeforeImport, CancellationToken cancellationToken)
{
2023-09-29 12:06:46 +05:00
var excelParser = excelParsers.FirstOrDefault(p => p.IdTemplate == options.IdTemplate && p.IdTypes.Contains(idType))
?? throw new ArgumentInvalidException(nameof(options.IdTemplate), "Невозможно импортировать файл");
2023-09-29 12:06:46 +05:00
if (idType != WellOperation.IdOperationTypePlan && idType != WellOperation.IdOperationTypeFact)
throw new ArgumentInvalidException(nameof(idType), "Операции не существует");
RowDto[] rows;
var validationErrors = new List<string>();
var sections = wellOperationRepository.GetSectionTypes();
var categories = wellOperationRepository.GetCategories(false);
switch (options.IdTemplate)
{
case 0:
options.SheetName = idType == WellOperation.IdOperationTypePlan
? DefaultTemplateInfo.SheetNamePlan
: DefaultTemplateInfo.SheetNameFact;
rows = excelParser.Parse(stream, options).ToArray();
break;
default:
if (string.IsNullOrWhiteSpace(options.SheetName))
throw new FileFormatException("Не указано название листа");
rows = excelParser.Parse(stream, options).ToArray();
break;
}
var operations = new List<WellOperationDto>();
foreach (var row in rows)
{
try
{
var section = sections.FirstOrDefault(s =>
string.Equals(s.Caption, row.Section, StringComparison.CurrentCultureIgnoreCase));
if (section is null)
throw new FileFormatException($"Лист '{options.SheetName}'. В строке '{row.Number}' не удалось определить секцию");
var category = categories.FirstOrDefault(c =>
string.Equals(c.Name, row.Category, StringComparison.CurrentCultureIgnoreCase));
if (category is null)
throw new FileFormatException($"Лист '{options.SheetName}'. В строке '{row.Number}' не удалось определить операцию");
if (row.DepthStart is not (>= 0d and <= 20_000d))
throw new FileFormatException($"Лист '{options.SheetName}'. Строка '{row.Number}' некорректная глубина на начало операции");
if (row.DepthEnd is not (>= 0d and <= 20_000d))
throw new FileFormatException($"Лист '{options.SheetName}'. Строка '{row.Number}' некорректная глубина на конец операции");
if (row.Date < dateLimitMin && row.Date > dateLimitMax)
throw new FileFormatException($"Лист '{options.SheetName}'. Строка '{row.Number}' неправильно получена дата начала операции");
if (operations.LastOrDefault()?.DateStart > row.Date)
throw new FileFormatException($"Лист '{options.SheetName}' строка '{row.Number}' дата позднее даты предыдущей операции");
if (row.Duration is not (>= 0d and <= 240d))
throw new FileFormatException($"Лист '{options.SheetName}'. Строка '{row.Number}' некорректная длительность операции");
operations.Add(new WellOperationDto
{
IdWell = idWell,
IdUser = idUser,
IdType = idType,
IdWellSectionType = section.Id,
IdCategory = category.Id,
CategoryInfo = row.CategoryInfo,
DepthStart = row.DepthStart,
DepthEnd = row.DepthEnd,
DateStart = row.Date,
DurationHours = row.Duration
});
}
catch (FileFormatException ex)
{
validationErrors.Add(ex.Message);
}
}
if (operations.Any() && operations.Min(o => o.DateStart) - operations.Max(o => o.DateStart) > drillingDurationLimitMax)
validationErrors.Add($"Лист {options.SheetName} содержит диапазон дат больше {drillingDurationLimitMax}");
if (validationErrors.Any())
throw new FileFormatException(string.Join("\r\n", validationErrors));
if(!operations.Any())
return;
if (deleteWellOperationsBeforeImport)
{
var existingOperations = await wellOperationRepository.GetAsync(new WellOperationRequest
{
IdWell = idWell
}, cancellationToken);
await wellOperationRepository.DeleteAsync(existingOperations.Select(o => o.Id), cancellationToken);
}
await wellOperationRepository.InsertRangeAsync(operations, cancellationToken);
}
}