forked from ddrilling/AsbCloudServer
130 lines
4.9 KiB
C#
130 lines
4.9 KiB
C#
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;
|
||
|
||
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, Stream stream, WellOperationParserOptionsDto options, bool deleteBeforeImport,
|
||
CancellationToken cancellationToken)
|
||
{
|
||
var excelParser = excelParsers.FirstOrDefault(p =>
|
||
p.IdTemplate == options.IdTemplate &&
|
||
p.IdTypes.Contains(options.IdType))
|
||
?? throw new ArgumentInvalidException(nameof(options.IdTemplate), "Невозможно импортировать файл");
|
||
|
||
IEnumerable<RowDto> rows;
|
||
var validationErrors = new List<string>();
|
||
|
||
var sections = wellOperationRepository.GetSectionTypes();
|
||
var categories = wellOperationRepository.GetCategories(false);
|
||
|
||
rows = options.IdTemplate switch
|
||
{
|
||
0 => excelParser.Parse(stream, options),
|
||
_ => excelParser.Parse(stream, options)
|
||
};
|
||
|
||
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 = options.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 (deleteBeforeImport)
|
||
{
|
||
var existingOperations = await wellOperationRepository.GetAsync(new WellOperationRequest
|
||
{
|
||
IdWell = idWell
|
||
}, cancellationToken);
|
||
|
||
await wellOperationRepository.DeleteAsync(existingOperations.Select(o => o.Id), cancellationToken);
|
||
}
|
||
|
||
await wellOperationRepository.InsertRangeAsync(operations, cancellationToken);
|
||
}
|
||
} |