forked from ddrilling/AsbCloudServer
Удалил старые реализации импорта/экспорта ГГД
This commit is contained in:
parent
1ccfa84e45
commit
39a1c874c0
@ -1,20 +0,0 @@
|
||||
using System.IO;
|
||||
using AsbCloudApp.Data.WellOperationImport;
|
||||
using AsbCloudApp.Data.WellOperationImport.Options;
|
||||
|
||||
namespace AsbCloudApp.Services.WellOperationImport;
|
||||
|
||||
/// <summary>
|
||||
/// Парсинг операций из excel файла
|
||||
/// </summary>
|
||||
public interface IWellOperationExcelParser<in TOptions>
|
||||
where TOptions : IWellOperationImportOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Метод парсинга документа
|
||||
/// </summary>
|
||||
/// <param name="stream"></param>
|
||||
/// <param name="options"></param>
|
||||
/// <returns></returns>
|
||||
SheetDto Parse(Stream stream, TOptions options);
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AsbCloudApp.Services.WellOperationImport;
|
||||
|
||||
/// <summary>
|
||||
/// Экспорт ГГД
|
||||
/// </summary>
|
||||
public interface IWellOperationExportService
|
||||
{
|
||||
/// <summary>
|
||||
/// Скачать в excel
|
||||
/// </summary>
|
||||
/// <param name="idWell"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task<Stream> ExportAsync(int idWell, CancellationToken cancellationToken);
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudApp.Data.WellOperationImport;
|
||||
|
||||
namespace AsbCloudApp.Services.WellOperationImport;
|
||||
|
||||
/// <summary>
|
||||
/// Импорт ГГД
|
||||
/// </summary>
|
||||
public interface IWellOperationImportService
|
||||
{
|
||||
/// <summary>
|
||||
/// Загрузить из excel список операций
|
||||
/// </summary>
|
||||
/// <param name="idWell"></param>
|
||||
/// <param name="idUser"></param>
|
||||
/// <param name="idType"></param>
|
||||
/// <param name="sheet"></param>
|
||||
IEnumerable<WellOperationDto> Import(int idWell, int idUser, int idType, SheetDto sheet);
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
using System.IO;
|
||||
|
||||
namespace AsbCloudApp.Services.WellOperationImport;
|
||||
|
||||
/// <summary>
|
||||
/// Сервис для получения шаблонов ГГД
|
||||
/// </summary>
|
||||
public interface IWellOperationImportTemplateService
|
||||
{
|
||||
/// <summary>
|
||||
/// Скачать шаблон для заполнения
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Stream GetExcelTemplateStream();
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using AsbCloudApp.Data.WellOperation;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services.ExcelServices.Templates.WellOperations;
|
||||
|
||||
public class WellOperationFactTemplate : ITemplateParameters
|
||||
{
|
||||
public string SheetName => "Факт";
|
||||
|
||||
public int HeaderRowsCount => 1;
|
||||
|
||||
public string FileName => "WellOperationFactTemplate.xlsx";
|
||||
|
||||
public IDictionary<string, Cell> Cells => new Dictionary<string, Cell>
|
||||
{
|
||||
{ nameof(WellOperationDto.WellSectionTypeCaption), new Cell(1, typeof(string)) },
|
||||
{ nameof(WellOperationDto.OperationCategoryName), new Cell(2, typeof(string)) },
|
||||
{ nameof(WellOperationDto.CategoryInfo), new Cell(3, typeof(string)) },
|
||||
{ nameof(WellOperationDto.DepthStart), new Cell(4, typeof(double)) },
|
||||
{ nameof(WellOperationDto.DepthEnd), new Cell(5, typeof(double)) },
|
||||
{ nameof(WellOperationDto.DateStart), new Cell(6, typeof(DateTime)) },
|
||||
{ nameof(WellOperationDto.DurationHours), new Cell(7, typeof(double)) },
|
||||
{ nameof(WellOperationDto.Comment), new Cell(8, typeof(string)) }
|
||||
};
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
namespace AsbCloudInfrastructure.Services.WellOperationImport.Constants;
|
||||
|
||||
public static class DefaultTemplateInfo
|
||||
{
|
||||
public const string SheetNamePlan = "План";
|
||||
public const string SheetNameFact = "Факт";
|
||||
|
||||
public const int HeaderRowsCount = 1;
|
||||
public const int ColumnSection = 1;
|
||||
public const int ColumnCategory = 2;
|
||||
public const int ColumnCategoryInfo = 3;
|
||||
public const int ColumnDepthStart = 4;
|
||||
public const int ColumnDepthEnd = 5;
|
||||
public const int ColumnDate = 6;
|
||||
public const int ColumnDuration = 7;
|
||||
public const int ColumnComment = 8;
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
namespace AsbCloudInfrastructure.Services.WellOperationImport.Constants;
|
||||
|
||||
public static class OperationAttributes
|
||||
{
|
||||
public const string CategoryInfo = "Описание";
|
||||
public const string SectionDiameter = "ОК";
|
||||
public const string Depth = "Забой";
|
||||
public const string Duration = "Время операции";
|
||||
public const string Date = "Дата окончания операции";
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
namespace AsbCloudInfrastructure.Services.WellOperationImport.Constants;
|
||||
|
||||
public static class Templates
|
||||
{
|
||||
public const int IdDefaultTemplate = 0;
|
||||
public const int IdGazpromKhantosTemplate = 1;
|
||||
}
|
@ -1,98 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services.WellOperationImport.FileParser.StringSimilarity;
|
||||
|
||||
public class CosineSimilarity
|
||||
{
|
||||
private const int DefaultK = 2;
|
||||
|
||||
protected int K { get; }
|
||||
|
||||
public CosineSimilarity(int k)
|
||||
{
|
||||
if (k <= 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(k), "k should be positive!");
|
||||
}
|
||||
|
||||
K = k;
|
||||
}
|
||||
|
||||
public CosineSimilarity() : this(DefaultK) { }
|
||||
|
||||
public double Similarity(IDictionary<string, int> profile1, IDictionary<string, int> profile2)
|
||||
=> DotProduct(profile1, profile2)
|
||||
/ (Norm(profile1) * Norm(profile2));
|
||||
|
||||
public Dictionary<string, int> GetProfile(string s)
|
||||
{
|
||||
var shingles = new Dictionary<string, int>();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(s))
|
||||
return shingles;
|
||||
|
||||
var cleanString = Stemming(s);
|
||||
|
||||
for (int i = 0; i < (cleanString.Length - K + 1); i++)
|
||||
{
|
||||
var shingle = cleanString.Substring(i, K);
|
||||
|
||||
if (shingles.TryGetValue(shingle, out var old))
|
||||
{
|
||||
shingles[shingle] = old + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
shingles[shingle] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return shingles;
|
||||
}
|
||||
|
||||
private static string Stemming(string s)
|
||||
{
|
||||
var cleaned = Regex.Replace(s.ToLower(), "[^a-zа-я0-9]", "");
|
||||
var words = cleaned.Split(' ');
|
||||
var filteredWords = words.Where(word => word.Length > 1).ToArray();
|
||||
return string.Concat(filteredWords);
|
||||
}
|
||||
|
||||
private static double Norm(IDictionary<string, int> profile)
|
||||
{
|
||||
double agg = 0;
|
||||
|
||||
foreach (var entry in profile)
|
||||
{
|
||||
agg += 1.0 * entry.Value * entry.Value;
|
||||
}
|
||||
|
||||
return Math.Sqrt(agg);
|
||||
}
|
||||
|
||||
private static double DotProduct(IDictionary<string, int> profile1, IDictionary<string, int> profile2)
|
||||
{
|
||||
var smallProfile = profile2;
|
||||
var largeProfile = profile1;
|
||||
|
||||
if (profile1.Count < profile2.Count)
|
||||
{
|
||||
smallProfile = profile1;
|
||||
largeProfile = profile2;
|
||||
}
|
||||
|
||||
double agg = 0;
|
||||
foreach (var entry in smallProfile)
|
||||
{
|
||||
if (!largeProfile.TryGetValue(entry.Key, out var i))
|
||||
continue;
|
||||
|
||||
agg += 1.0 * entry.Value * i;
|
||||
}
|
||||
|
||||
return agg;
|
||||
}
|
||||
}
|
@ -1,92 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using AsbCloudApp.Data.WellOperationImport;
|
||||
using AsbCloudApp.Data.WellOperationImport.Options;
|
||||
using AsbCloudApp.Services.WellOperationImport;
|
||||
using AsbCloudDb.Model;
|
||||
using AsbCloudInfrastructure.Services.WellOperationImport.Constants;
|
||||
using ClosedXML.Excel;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services.WellOperationImport.FileParser;
|
||||
|
||||
public class WellOperationDefaultExcelParser : IWellOperationExcelParser<WellOperationImportDefaultOptionsDto>
|
||||
{
|
||||
public SheetDto Parse(Stream stream, WellOperationImportDefaultOptionsDto options)
|
||||
{
|
||||
using var workbook = new XLWorkbook(stream);
|
||||
|
||||
return ParseWorkbook(workbook, options);
|
||||
}
|
||||
|
||||
private static SheetDto ParseWorkbook(IXLWorkbook workbook, WellOperationImportDefaultOptionsDto options)
|
||||
{
|
||||
var sheetName = options.IdType == WellOperation.IdOperationTypePlan
|
||||
? DefaultTemplateInfo.SheetNamePlan
|
||||
: DefaultTemplateInfo.SheetNameFact;
|
||||
|
||||
var sheet = workbook.GetWorksheet(sheetName);
|
||||
|
||||
return ParseSheet(sheet);
|
||||
}
|
||||
|
||||
private static SheetDto ParseSheet(IXLWorksheet sheet)
|
||||
{
|
||||
if (sheet.RangeUsed().RangeAddress.LastAddress.ColumnNumber < 7)
|
||||
throw new FileFormatException($"Лист {sheet.Name} содержит меньшее количество столбцов.");
|
||||
|
||||
var count = sheet.RowsUsed().Count() - DefaultTemplateInfo.HeaderRowsCount;
|
||||
|
||||
switch (count)
|
||||
{
|
||||
case > 1024:
|
||||
throw new FileFormatException($"Лист {sheet.Name} содержит слишком большое количество операций.");
|
||||
case <= 0:
|
||||
return new SheetDto { Name = sheet.Name };
|
||||
}
|
||||
|
||||
var rows = new RowDto[count];
|
||||
|
||||
var cellValuesErrors = new List<string>();
|
||||
|
||||
for (int i = 0; i < rows.Length; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
var xlRow = sheet.Row(1 + i + DefaultTemplateInfo.HeaderRowsCount);
|
||||
|
||||
rows[i] = ParseRow(xlRow);
|
||||
}
|
||||
catch (FileFormatException ex)
|
||||
{
|
||||
cellValuesErrors.Add(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
if (cellValuesErrors.Any())
|
||||
throw new FileFormatException(string.Join("\r\n", cellValuesErrors));
|
||||
|
||||
return new SheetDto
|
||||
{
|
||||
Name = sheet.Name,
|
||||
Rows = rows
|
||||
};
|
||||
}
|
||||
|
||||
private static RowDto ParseRow(IXLRow xlRow)
|
||||
{
|
||||
return new RowDto
|
||||
{
|
||||
Number = xlRow.RowNumber(),
|
||||
Section = xlRow.Cell(DefaultTemplateInfo.ColumnSection).GetCellValue<string>(),
|
||||
Category = xlRow.Cell(DefaultTemplateInfo.ColumnCategory).GetCellValue<string>(),
|
||||
CategoryInfo = xlRow.Cell(DefaultTemplateInfo.ColumnCategoryInfo).GetCellValue<string?>(),
|
||||
DepthStart = xlRow.Cell(DefaultTemplateInfo.ColumnDepthStart).GetCellValue<double>(),
|
||||
DepthEnd = xlRow.Cell(DefaultTemplateInfo.ColumnDepthEnd).GetCellValue<double>(),
|
||||
Date = xlRow.Cell(DefaultTemplateInfo.ColumnDate).GetCellValue<DateTime>(),
|
||||
Duration = xlRow.Cell(DefaultTemplateInfo.ColumnDuration).GetCellValue<double>(),
|
||||
Comment = xlRow.Cell(DefaultTemplateInfo.ColumnComment).GetCellValue<string?>()
|
||||
};
|
||||
}
|
||||
}
|
@ -1,227 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using AsbCloudApp.Data.WellOperationImport;
|
||||
using AsbCloudApp.Data.WellOperationImport.Options;
|
||||
using AsbCloudApp.Exceptions;
|
||||
using AsbCloudApp.Services.WellOperationImport;
|
||||
using AsbCloudInfrastructure.Services.WellOperationImport.Constants;
|
||||
using AsbCloudInfrastructure.Services.WellOperationImport.FileParser.StringSimilarity;
|
||||
using ClosedXML.Excel;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services.WellOperationImport.FileParser;
|
||||
|
||||
public class WellOperationGazpromKhantosExcelParser : IWellOperationExcelParser<WellOperationImportGazpromKhantosOptionsDto>
|
||||
{
|
||||
private class Operation
|
||||
{
|
||||
public int RowNumber { get; set; }
|
||||
|
||||
public string? CategoryInfo { get; set; }
|
||||
|
||||
public double SectionDiameter { get; set; }
|
||||
|
||||
public double Depth { get; set; }
|
||||
|
||||
public double Duration { get; set; }
|
||||
|
||||
public DateTime Date { get; set; }
|
||||
}
|
||||
|
||||
private readonly CosineSimilarity cosineSimilarity = new();
|
||||
|
||||
private readonly Dictionary<string, string> operationDict = InitDict("Operations.txt", '=');
|
||||
private readonly Dictionary<string, string> sectionDict = InitDict("Sections.txt", '=');
|
||||
private readonly Dictionary<string, string> operationAttributesDict = InitDict("OperationAttributes.txt", '=');
|
||||
|
||||
public SheetDto Parse(Stream stream, WellOperationImportGazpromKhantosOptionsDto options)
|
||||
{
|
||||
using var workbook = new XLWorkbook(stream);
|
||||
|
||||
return ParseWorkBook(workbook, options);
|
||||
}
|
||||
|
||||
private SheetDto ParseWorkBook(IXLWorkbook workbook, WellOperationImportGazpromKhantosOptionsDto options)
|
||||
{
|
||||
if (options.StartRow is < 1 or > 1048576)
|
||||
throw new ArgumentInvalidException(nameof(options.StartRow), "Некорректное значение начальной строки");
|
||||
|
||||
if (options.EndRow is < 1 or > 1048576)
|
||||
throw new ArgumentInvalidException(nameof(options.EndRow), "Некорректное значение конечной строки");
|
||||
|
||||
if (options.EndRow < options.StartRow)
|
||||
throw new ArgumentInvalidException(nameof(options.EndRow), "Конечный номер строки не может быть больше начального");
|
||||
|
||||
var sheet = workbook.GetWorksheet(options.SheetName);
|
||||
return ParseSheet(sheet, options.StartRow, options.EndRow);
|
||||
}
|
||||
|
||||
private SheetDto ParseSheet(IXLWorksheet sheet, int startRow, int endRow)
|
||||
{
|
||||
var operationAttributes = GetOperationAttributes(sheet.RowsUsed());
|
||||
|
||||
if (operationAttributes is null)
|
||||
return new SheetDto { Name = sheet.Name };
|
||||
|
||||
var rowsCount = endRow - startRow + 1;
|
||||
|
||||
var operations = new List<Operation>();
|
||||
|
||||
var cellValuesErrors = new List<string>();
|
||||
|
||||
for (int i = 0; i < rowsCount; i++)
|
||||
{
|
||||
var xlRow = sheet.Row(startRow + i);
|
||||
|
||||
try
|
||||
{
|
||||
operations.Add(new Operation
|
||||
{
|
||||
RowNumber = xlRow.RowNumber(),
|
||||
CategoryInfo = xlRow.Cell(operationAttributes[OperationAttributes.CategoryInfo]).GetCellValue<string?>(),
|
||||
SectionDiameter =xlRow.Cell(operationAttributes[OperationAttributes.SectionDiameter]).GetCellValue<double>(),
|
||||
Depth = xlRow.Cell(operationAttributes[OperationAttributes.Depth]).GetCellValue<double>(),
|
||||
Duration = xlRow.Cell(operationAttributes[OperationAttributes.Duration]).GetCellValue<double>(),
|
||||
Date = xlRow.Cell(operationAttributes[OperationAttributes.Date]).GetCellValue<DateTime>()
|
||||
});
|
||||
}
|
||||
catch (FileFormatException ex)
|
||||
{
|
||||
cellValuesErrors.Add(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
if (cellValuesErrors.Any())
|
||||
throw new FileFormatException(string.Join("\r\n", cellValuesErrors));
|
||||
|
||||
return new SheetDto()
|
||||
{
|
||||
Name = sheet.Name,
|
||||
Rows = BuildRows()
|
||||
};
|
||||
|
||||
IEnumerable<(double Diameter, string Name)> BuildSections()
|
||||
{
|
||||
var groupedOperations = operations.GroupBy(o => o.SectionDiameter)
|
||||
.Select(s => new
|
||||
{
|
||||
Diameter = s.Key,
|
||||
CategoryInfo = string.Concat(s.Select(o => o.CategoryInfo))
|
||||
});
|
||||
|
||||
var repeatedSections = new[] { "xвостовик" };
|
||||
|
||||
var sections = new List<(double diameter, string section)>();
|
||||
|
||||
foreach (var groupedOperation in groupedOperations)
|
||||
{
|
||||
var sectionNamesSet = new HashSet<string>(sections.Select(s => s.section));
|
||||
|
||||
sections.Add(new ValueTuple<double, string>(groupedOperation.Diameter, sectionDict.FirstOrDefault(item =>
|
||||
groupedOperation.CategoryInfo.Contains(item.Key) &&
|
||||
(!sectionNamesSet.Contains(item.Value) || repeatedSections.Contains(item.Value.ToLowerInvariant()))).Value));
|
||||
}
|
||||
|
||||
return sections;
|
||||
}
|
||||
|
||||
IEnumerable<RowDto> BuildRows()
|
||||
{
|
||||
if (!operations.Any())
|
||||
return Enumerable.Empty<RowDto>();
|
||||
|
||||
var rows = new List<RowDto>();
|
||||
|
||||
for (int i = 0; i < operations.Count; i++)
|
||||
{
|
||||
var currentOperation = operations[i];
|
||||
var nextOperation = i + 1 < operations.Count ? operations[i + 1] : currentOperation;
|
||||
|
||||
rows.Add(new RowDto
|
||||
{
|
||||
Number = currentOperation.RowNumber,
|
||||
Section = BuildSections().FirstOrDefault(s => Math.Abs(s.Diameter - currentOperation.SectionDiameter) < 0.1).Name,
|
||||
Category = GetValueDictionary(operationDict, currentOperation.CategoryInfo, 0.3),
|
||||
CategoryInfo = currentOperation.CategoryInfo,
|
||||
DepthStart = currentOperation.Depth,
|
||||
DepthEnd = nextOperation.Depth,
|
||||
Duration = currentOperation.Duration,
|
||||
Date = currentOperation.Date.AddHours(-currentOperation.Duration)
|
||||
});
|
||||
}
|
||||
|
||||
return rows;
|
||||
}
|
||||
}
|
||||
|
||||
private IDictionary<string, int>? GetOperationAttributes(IXLRows xlRows)
|
||||
{
|
||||
const int countOperationAttributes = 5;
|
||||
|
||||
IDictionary<string, int>? operationAttributes = null;
|
||||
|
||||
foreach (var xlRow in xlRows)
|
||||
{
|
||||
operationAttributes = new Dictionary<string, int>();
|
||||
|
||||
var cells = xlRow.CellsUsed().ToArray();
|
||||
|
||||
foreach (var cell in cells)
|
||||
{
|
||||
var operationAttribute = GetValueDictionary(operationAttributesDict, cell.GetCellValue<string>(), 0.7);
|
||||
|
||||
if (operationAttribute is null || operationAttributes.Any(a => a.Key == operationAttribute))
|
||||
continue;
|
||||
|
||||
operationAttributes.Add(operationAttribute, cell.Address.ColumnNumber);
|
||||
}
|
||||
|
||||
if (operationAttributes.Count >= countOperationAttributes)
|
||||
break;
|
||||
}
|
||||
|
||||
return operationAttributes is not null && operationAttributes.Count == countOperationAttributes ? operationAttributes : null;
|
||||
}
|
||||
|
||||
private string? GetValueDictionary(IDictionary<string, string> dict, string? cellValue, double? minSimilarity)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(cellValue))
|
||||
return null;
|
||||
|
||||
var similarValues = new List<(double similarity, string value)>();
|
||||
|
||||
var profile1 = cosineSimilarity.GetProfile(cellValue);
|
||||
|
||||
foreach (var item in dict)
|
||||
{
|
||||
var profile2 = cosineSimilarity.GetProfile(item.Key);
|
||||
|
||||
var similarity = cosineSimilarity.Similarity(profile1, profile2);
|
||||
|
||||
similarValues.Add((similarity, item.Value));
|
||||
}
|
||||
|
||||
var mostSimilarValue = similarValues.MaxBy(v => v.similarity);
|
||||
|
||||
return minSimilarity.HasValue && mostSimilarValue.similarity >= minSimilarity ? mostSimilarValue.value : null;
|
||||
}
|
||||
|
||||
private static Dictionary<string, string> InitDict(string fileName, char separator)
|
||||
{
|
||||
var resourceName = Assembly.GetExecutingAssembly()
|
||||
.GetManifestResourceNames()
|
||||
.FirstOrDefault(n => n.EndsWith(fileName))!;
|
||||
|
||||
var stream = Assembly.GetExecutingAssembly()
|
||||
.GetManifestResourceStream(resourceName)!;
|
||||
|
||||
using var reader = new StreamReader(stream);
|
||||
|
||||
return reader.ReadToEnd().Split('\r')
|
||||
.Where(s => !string.IsNullOrWhiteSpace(s))
|
||||
.Select(line => line.Split(separator))
|
||||
.ToDictionary(parts => parts[0].Trim(), parts => parts[1].Trim());
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
Описание=Описание
|
||||
ОК=ОК
|
||||
Секция=ОК
|
||||
Забой, м=Забой
|
||||
Время=Время операции
|
||||
Плановое время бурения, сут=Время операции
|
||||
Окончание=Дата окончания операции
|
||||
Дата окончания План РГ=Дата окончания операции
|
@ -1,201 +0,0 @@
|
||||
Сборка КНБК=Сборка КНБК
|
||||
Сборка роторной КНБК=Сборка КНБК
|
||||
Шаблонирование спуск КНБК=Шаблонирование перед спуском
|
||||
Бурение под направлением=Бурение ротором
|
||||
Шаблонирование перед спуском=Шаблонирование перед спуском
|
||||
Шаблонировка пробуренного интервала + промывка на забое+ подъем КНБК=Шаблонирование перед спуском
|
||||
Разборка КНБК=Разборка КНБК
|
||||
ПР к спуску направления 324мм=ПЗР при спуске ОК
|
||||
Спуск направления=Спуск ОК
|
||||
Спуск направления 324мм=Спуск ОК
|
||||
Цементаж направления 324мм=Цементирование
|
||||
ОЗЦ. Оборудование устья.=ОЗЦ
|
||||
ОЗЦ. Чистка забурочной ямы. Чистка ВШН. Отворот доп. патрубка. ЗГР=ОЗЦ
|
||||
Перетяжка талевого каната / замена.=Перетяжка талевого каната
|
||||
Шаблонирование подъём КНБК=Шаблонировка подъем БИ, продувка
|
||||
Сборка СБТ 127мм-300м=Сборка БИ с мостков на подсвечник
|
||||
Сборка КНБК для бурения кондуктора=Сборка КНБК
|
||||
Сборка КНБК для бурения. Компоновка БК согласно собранного БИ в п.10=Сборка КНБК
|
||||
Cпуск КНБК=Спуск КНБК
|
||||
Cпуск КНБК со сборкой БИ с мостков=Спуск бурильного инструмента со сборкой с мостков
|
||||
Разбурка оснастки (ЦКОД, цем.стакан, БК), замена раствора=Разбуривание тех.оснастки
|
||||
Бурение под кондуктор. Наращивание св.=Бурение ротором
|
||||
Промывка, ОБР, МBТ БР<70 кг/м3=Промывка
|
||||
Промывка на забое=Промывка
|
||||
Шаблонирование (подъем)=Шаблонировка во время бурения
|
||||
Шаблонирование (спуск)=Шаблонировка во время бурения
|
||||
Промывка на забое. Прокачка ВУС, ОБР, МBТ БР <70 кг/м3=Промывка
|
||||
Подъем=Подъем КНБК
|
||||
Разборка КНБК с телесистемой=Разборка КНБК
|
||||
ПЗР к спуску ОК 245мм=ПЗР при спуске ОК
|
||||
Спуск ОК 245мм с промежуточными промывками (500 м, 1000м). Вывоз БР с БДЕ=Спуск ОК
|
||||
Промывка перед цементажем=Промывка при спуске ОК
|
||||
Цементаж кондуктора 245мм=Цементирование
|
||||
Монтаж ОУС. Вывоз БР, Чистка емкостей=Чистка ЦСГО/емкостного блока
|
||||
Монтаж ОУС=Монтаж ПВО
|
||||
Заготовка бурового раствора, чистка емкостей.=Опрессовка ПВО
|
||||
Монтаж ПВО, монтаж разрезной воронки и устьевого желоба. Вывоз БР, заготовка БР=Монтаж ПВО
|
||||
Опрессовка глухих плашек ППГ, БГ, БД , выкидных линий, крестовины с коренными задвижками. ЗБР=Опрессовка ПВО
|
||||
Сборка КНБК на бурение=Сборка КНБК
|
||||
Сборка СБТ 127мм-465м=Сборка БИ с мостков на подсвечник
|
||||
Спуск КНБК со сборкой с мостков СБТ -127 (1700м)=Спуск КНБК
|
||||
Сборка КНБК на бурение транспортного ствола=Сборка КНБК
|
||||
Опрессовка трубных плашек, ПУГ=Опрессовка ПВО
|
||||
Разбурка оснастки (ЦКОД, цем.стакан, БК, углубление на 2 метра ниже БК, опрессовка цементного кольца)=Разбуривание тех.оснастки
|
||||
Разбурка БК, ЦКОДа и цем.стакана=Разбуривание тех.оснастки
|
||||
Перевод скважины на новый раствор, чистка ЦСГО=Промывка - перевод скважины на новый раствор
|
||||
Перевод скважины на новый буровой раствор=Промывка - перевод скважины на новый раствор
|
||||
Бурение транспортного ствола наращ.св. (прокачка укрепляющих пачек ч/з каждые 150-200м)=Бурение ротором
|
||||
Промывка после ХМ св TVD - 1660 м (ниже на 50 м)=Промывка
|
||||
Чистка ЦСГО (опрессовка цем. кольца кондуктора во время чистки ЦСГО)=Чистка ЦСГО/емкостного блока
|
||||
Промывка после Алымской св TVD - 2140 м (ниже на 50 м)=Промывка
|
||||
Бурение транспортного ствола наращ. cв. (прокачка укрепляющих пачек ч/з каждые 150-200м).=Бурение ротором
|
||||
Бурение транспортного ствола (1000м первые сутки бурения)=Бурение ротором
|
||||
Подъем КНБК шаблонировка ствола скважины=Шаблонировка подъем БИ, продувка
|
||||
Промывка (по согласованию с ЦУСС)=Промывка
|
||||
Шаблонировка. Подъем КНБК (по согласованию с ЦУСС)=Шаблонировка во время бурения
|
||||
Шаблонировка.Спуск КНБК со сборкой БИ 300м (по согласованию с ЦУСС)=Шаблонировка во время бурения
|
||||
Промывка=Промывка
|
||||
Шаблонировка. Подъем КНБК=Шаблонировка во время бурения
|
||||
Шаблонировка.Спуск КНБК=Шаблонировка во время бурения
|
||||
Разборка КНБК с т/с=Разборка КНБК
|
||||
Промывка на забое, прокачка кольмат. пачки=Помывка
|
||||
ПЗР к спуску ОК-178мм.=ПЗР при спуске ОК
|
||||
Спуск ОК 178 мм (до устья, не потайная) с промежуточными промывками=Спуск ОК
|
||||
Цементирование ОК-178мм=Цементирование
|
||||
Отворот и выброс допускной трубы, демонтаж ПВО, замыв шурфа для выброса СБТ-127мм, чистка емкостей, приготовление БР=Демонтаж ПВО
|
||||
Промывка, установка смазывающей пачки=Промывка
|
||||
Выброс СБТ-127мм на мостки, чистка емкостей, приготовление БР=Подъем БИ с выбросом на мостки
|
||||
Подъем КНБК с выбросом БИ - 500м (выброс согласовать с куратором ЦУСС)=Подъем КНБК
|
||||
Монтаж ПВО, замена трубных плашек 127мм на 102мм, замена рабочего переводника на СВП, приготовление БР=Перетяжка талевого каната
|
||||
ПЗР к спуску ОК 178мм=ПЗР при спуске ОК
|
||||
Спуск ОК 178мм с промывками. Вывоз БР с БДЕ=Спуск ОК
|
||||
Цементирование 178мм ОК. Вывоз БР с БДЕ=Цементирование
|
||||
Частичный демонтаж ПВО=Демонтаж ПВО
|
||||
Выброс БИ 127 на мостки - 1600м (Оставляем БИ 127 1400 м на бурение под кондуктор). Вывоз БР, чистка емкостей=Подъем БИ с выбросом на мостки
|
||||
Частичный монтаж ПВО=Монтаж ПВО
|
||||
Опрессовка (200 атм) глухих плашек ППГ, БГ, БД, выкидных линий, крестовины с коренными задвижками, ЗБР. Сборка БИ-102мм - 1000м для бурения ГС свечами.=Опрессовка ПВО
|
||||
Сборка КНБК на бурение секции под хвостовик 114мм=Сборка КНБК
|
||||
Спуск КНБК со сборкой БИ 102 и промежуточными промывками.=Промывка - перевод скважины на новый раствор
|
||||
Опрессовка трубных плашек ППГ, ПУГ. Промывка, перезапись гаммы=Опрессовка ПВО
|
||||
Разбурка оснастки (ЦКОД, цем.стакан, БК)=Разбуривание тех.оснастки
|
||||
Перевод на новый раствор=Промывка - перевод скважины на новый раствор
|
||||
Чистка ЦСГО=Чистка ЦСГО/емкостного блока
|
||||
Бурение горизонтального участка скважины (прокачка укрепляющих пачек ч/з каждые 100 м)=Бурение ротором
|
||||
Подъем БИ в БК Ø178мм.=Подъем КНБК
|
||||
Спуск БИ со сборкой ТБТ 88,9мм на опрессовку (20м до БК 178)=Спуск КНБК
|
||||
Опрессовка БИ, установка на подсвечник ТБТ=Опрессовка БИ
|
||||
Проработка в 2 этапа:1 этап - прямая принудительная проработка; 2 этап - спуск на "сухую"(имитация спуска хвостовика)=Проработка принудительная
|
||||
Cборка хвостовика=Сборка хвостовика 114мм (согласно схеме)
|
||||
Промывка, прокачка ВУС=Промывка
|
||||
Подъем КНБК=Подъем КНБК
|
||||
ПЗР к спуску хвостовика=ПЗР при спуске ОК
|
||||
Сборка хвостовика 114мм (согласно схеме)=Сборка хвостовика 114мм (согласно схеме)
|
||||
Спуск хвостовика 114мм на БИ. В БК 178 перевод на тех.воду (по согл.с ЦУСС)=Спуск ОК
|
||||
Активация подвески (4ч). Перевод на жидкость заканчивания (2ч).=Активация подвески, опрессовка
|
||||
Подъем БИ с выбросом на мостки. Оставляем ТБТ 89 (800 м) на следующую скв=Подъем БИ с выбросом на мостки
|
||||
Демонтаж ПВО=Демонтаж ПВО
|
||||
Монтаж, опрессовка ФА=Монтаж, опрессовка ФА
|
||||
5% времени на ТО БУ=Ремонт
|
||||
Монтаж ФА=Монтаж, опрессовка ФА
|
||||
Подъем разъединителя с выбросом СБТ-102мм на мостки=Подъем инструмента
|
||||
Активация подвески. Перевод на жидкость заканчивания. Опрессовка пакера подвески хвостовика.=Активация подвески (потайной колонны, хвостовика)
|
||||
ПР к спуску хвостовика=ПЗР при спуске ОК
|
||||
Подъем КНБК с частичным выбросом СБТ-102мм на приемные мостки=Подъем БИ с выбросом на мостки
|
||||
Бурение горизонтального участка скважины (прокачка укрепляющих пачек ч/з каждые 100м)=Бурение ротором
|
||||
Промывка перезапись ГК=Промывка
|
||||
Спуск КНБК со сборкой СБТ-102мм с приемных мостков, с промежуточными промывками каждые 500м=Спуск бурильного инструмента со сборкой с мостков
|
||||
Сборка КНБК для бурения горизонтального участка скважины=Сборка БИ с мостков на подсвечник
|
||||
Опрессовка глухих плашек ППГ, БГ, БД, выкидных линий, крестовины с коренными задвижками, приготовление бур.раствора=Опрессовка ПВО
|
||||
ВМР=ВМР
|
||||
Долив затруба при подъёме=Долив затруба при подъёме
|
||||
Закачка/прокачка пачки=Закачка/прокачка пачки
|
||||
Комплекс ГИС на жестком кабеле=Комплекс ГИС на жестком кабеле
|
||||
Комплекс ГИС на кабеле=Комплекс ГИС на кабеле
|
||||
Комплекс ГИС на трубах=Комплекс ГИС на трубах
|
||||
Контролируемое ГНВП=Контролируемое ГНВП
|
||||
Ловильные работы=Ловильные работы
|
||||
Наработка жёлоба=Наработка жёлоба
|
||||
Наращивание=Наращивание
|
||||
НПВ / прочее=НПВ / прочее
|
||||
Обвязка устья с циркуляционной системой=Обвязка устья с циркуляционной системой
|
||||
Оборудование устья=Оборудование устья
|
||||
Обработка БР=Обработка БР
|
||||
Обработка раствора (несоответствие параметров)=Обработка раствора (несоответствие параметров)
|
||||
Ожидание=Ожидание
|
||||
Определение места прихвата и ЛМ=Определение места прихвата и ЛМ
|
||||
Опрессовка ОК=Опрессовка ОК
|
||||
Ориентирование ТС при бурении=Ориентирование ТС при бурении
|
||||
Отворот допускной трубы=Отворот допускной трубы
|
||||
Перезапись гаммы-каротажа=Перезапись гаммы-каротажа
|
||||
Перемонтаж ПВО=Перемонтаж ПВО
|
||||
ПЗР к спуску УЭЦН=ПЗР к спуску УЭЦН
|
||||
ПЗР при сборке КНБК=ПЗР при сборке КНБК
|
||||
ПЗР при цементировании=ПЗР при цементировании
|
||||
Поглощение=Поглощение
|
||||
Подготовка ствола скважины. Перезапись ГК в интервале установки КО.=Подготовка ствола скважины. Перезапись ГК в интервале установки КО.
|
||||
Подъем БИ с выбросом на мостки=Подъем БИ с выбросом на мостки
|
||||
подъем ОК=подъем ОК
|
||||
Подъем приборов ГИС (на трубах)=Подъем приборов ГИС (на трубах)
|
||||
Полная замена талевого каната=Полная замена талевого каната
|
||||
ПР перед забуркой направления=ПР перед забуркой направления
|
||||
Приготовление БР=Приготовление БР
|
||||
Продувка манифольда=Продувка манифольда
|
||||
Промывка перед наращиванием=Промывка перед наращиванием
|
||||
Проработка во время бурения=Проработка во время бурения
|
||||
Проработка перед наращиванием=Проработка перед наращиванием
|
||||
Работа яссом=Работа яссом
|
||||
Разборка комплекса приборов ГИС=Разборка комплекса приборов ГИС
|
||||
Разбуривание тех.оснастк=Разбуривание тех.оснастки
|
||||
Расхаживани=Расхаживание
|
||||
Ревизия КНБК/инструмента/ЗТС=Ревизия КНБК/инструмента/ЗТС
|
||||
Ремонт бурового оборудования=Ремонт бурового оборудования
|
||||
Сальникообразование=Сальникообразование
|
||||
Сборка и спуск ТБТ=Сборка и спуск ТБТ
|
||||
Сборка комплекса приборов ГИС=Сборка комплекса приборов ГИС
|
||||
Сборка устройства ориентирования КО=Сборка устройства ориентирования КО
|
||||
Смена рабочего переводника ВСП=Смена рабочего переводника ВСП
|
||||
СПО - колокол=СПО - колокол
|
||||
СПО - метчик=СПО - метчик
|
||||
СПО - овершот=СПО - овершот
|
||||
СПО - труболовка=СПО - труболовка
|
||||
Спуск БИ со сборкой с мостков=Спуск БИ со сборкой с мостков
|
||||
Спуск инструмента=Спуск инструмента
|
||||
Спуск инструмента с проработкой=Спуск инструмента с проработкой
|
||||
Спуск КО на транспотрной колонне=Спуск КО на транспотрной колонне
|
||||
Спуск приборов ГИС (на трубах)=Спуск приборов ГИС (на трубах)
|
||||
Срезка=Срезка
|
||||
Тайм-дриллинг=Тайм-дриллинг
|
||||
Тех.отстой=Тех.отстой
|
||||
Торпедирование (встряхивание)=Торпедирование (встряхивание)
|
||||
Торпедирование (отстрел)=Торпедирование (отстрел)
|
||||
Удержание в клиньях=Удержание в клиньях
|
||||
Установка ванн=Установка ванн
|
||||
Утяжеление БР=Утяжеление БР
|
||||
Учебная тревога "Выброс"=Учебная тревога "Выброс"
|
||||
Фрезеровка=Фрезеровка
|
||||
Шаблонировка подъем БИ, продувка=Шаблонировка подъем БИ, продувка
|
||||
Шаблонировка перед наращиванием=Шаблонировка перед наращиванием
|
||||
Демонтаж ПВО ( переоборудование устья скважины). Вывоз БР=Демонтаж ПВО
|
||||
Сборка БИ 127/147с мостков установкой на подсвечник=Сборка БИ с мостков на подсвечник
|
||||
Спуск приборов комплекса АМАК.=Спуск приборов ГИС (на трубах)
|
||||
Подъем с записью=Подъем приборов ГИС (на трубах)
|
||||
ОЗЦ под давлением (по согласованию с ЦУСС)=ОЗЦ
|
||||
"Демонтаж ПВО ( переоборудование устья скважины). Вывоз БР=Демонтаж ПВО
|
||||
Сборка CБТ-127 (0м) с мостков установкой на подсвечник (оставлено СБТ-127 (1500м) с пердыдущей скв). Заготовка БР=Сборка БИ с мостков на подсвечник
|
||||
ПЗР к спуску ОК=ПЗР при спуске ОК
|
||||
Выброс СБТ 127 (2100м), оставляется СБТ-127 (700 м) на след скв. ЗБР, чистка емкостей, вывоз БР.=Подъем БИ с выбросом на мостки
|
||||
Монтаж ПВО повторный (смена плашек ПВО). ЗБР, чистка емкостей, вывоз БР=Монтаж ПВО
|
||||
Опрессовка ПВО (200 атм), глухие=Опрессовка ПВО
|
||||
Сборка ТБТ на 2 этапе (кол-во по согласованию с ЦУСС). Подъем/спуск БИ со сборкой ТБТ 102 мм. Опрессовка БИ (1.5 ч)=Сборка и спуск ТБТ
|
||||
Спуск пакера=Спуск пакера
|
||||
Запись гамма-каратожа=Запись гамма-каратожа
|
||||
Шаблонирование спуск БИ=Шаблонирование спуск БИ
|
||||
Сборка клин-отклонителя=Сборка клин-отклонителя
|
||||
Ориентирование и посадка клина-отклонителя=Ориентирование и посадка клина-отклонителя
|
||||
Протяжка подъемного патрубка подвески=Протяжка подъемного патрубка подвески
|
||||
Подъем клина-отклонителя=Подъем клина-отклонителя
|
||||
Стыковка стингера с хвостовиком основного ствола=Стыковка стингера с хвостовиком основного ствола
|
||||
Ориентирование и установка стыковочного узла хвостовика=Ориентирование и установка стыковочного узла хвостовика
|
||||
Бурение с отбором керна=Бурение с отбором керна
|
||||
Работа пакером в обсадной колонне=Работа пакером в обсадной колонне
|
@ -1,7 +0,0 @@
|
||||
направ=Направление
|
||||
конд=Кондуктор
|
||||
техн=Техническая колонна
|
||||
экспл=Эксплуатационная колонна
|
||||
транс=Транспортный ствол
|
||||
пилот=Пилотный ствол
|
||||
хвост=Хвостовик
|
Binary file not shown.
@ -1,102 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudApp.Repositories;
|
||||
using AsbCloudApp.Requests;
|
||||
using AsbCloudApp.Services.WellOperationImport;
|
||||
using AsbCloudInfrastructure.Services.WellOperationImport.Constants;
|
||||
using ClosedXML.Excel;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services.WellOperationImport;
|
||||
|
||||
public class WellOperationExportService : IWellOperationExportService
|
||||
{
|
||||
private readonly IWellOperationRepository wellOperationRepository;
|
||||
private readonly IWellOperationImportTemplateService wellOperationImportTemplateService;
|
||||
private readonly IWellOperationCategoryRepository wellOperationCategoryRepository;
|
||||
|
||||
public WellOperationExportService(
|
||||
IWellOperationRepository wellOperationRepository,
|
||||
IWellOperationImportTemplateService wellOperationImportTemplateService,
|
||||
IWellOperationCategoryRepository wellOperationCategoryRepository)
|
||||
{
|
||||
this.wellOperationRepository = wellOperationRepository;
|
||||
this.wellOperationImportTemplateService = wellOperationImportTemplateService;
|
||||
this.wellOperationCategoryRepository = wellOperationCategoryRepository;
|
||||
}
|
||||
|
||||
public async Task<Stream> ExportAsync(int idWell, CancellationToken cancellationToken)
|
||||
{
|
||||
var operations = await wellOperationRepository.GetAsync(new WellOperationRequest()
|
||||
{
|
||||
IdWell = idWell
|
||||
}, cancellationToken);
|
||||
|
||||
return MakeExcelFileStream(operations);
|
||||
}
|
||||
|
||||
private Stream MakeExcelFileStream(IEnumerable<WellOperationDto> operations)
|
||||
{
|
||||
using Stream ecxelTemplateStream = wellOperationImportTemplateService.GetExcelTemplateStream();
|
||||
|
||||
using var workbook = new XLWorkbook(ecxelTemplateStream);
|
||||
AddOperationsToWorkbook(workbook, operations);
|
||||
|
||||
var memoryStream = new MemoryStream();
|
||||
workbook.SaveAs(memoryStream, new SaveOptions { });
|
||||
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||
return memoryStream;
|
||||
}
|
||||
|
||||
private void AddOperationsToWorkbook(XLWorkbook workbook, IEnumerable<WellOperationDto> operations)
|
||||
{
|
||||
var planOperations = operations.Where(o => o.IdType == 0);
|
||||
if (planOperations.Any())
|
||||
{
|
||||
var sheetPlan = workbook.GetWorksheet(DefaultTemplateInfo.SheetNamePlan);
|
||||
|
||||
AddOperationsToSheet(sheetPlan, planOperations);
|
||||
}
|
||||
|
||||
var factOperations = operations.Where(o => o.IdType == 1);
|
||||
if (factOperations.Any())
|
||||
{
|
||||
var sheetFact = workbook.GetWorksheet(DefaultTemplateInfo.SheetNameFact);
|
||||
|
||||
AddOperationsToSheet(sheetFact, factOperations);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddOperationsToSheet(IXLWorksheet sheet, IEnumerable<WellOperationDto> operations)
|
||||
{
|
||||
var operationsToArray = operations.ToArray();
|
||||
|
||||
var sections = wellOperationRepository.GetSectionTypes();
|
||||
var categories = wellOperationCategoryRepository.Get(false);
|
||||
|
||||
for (int i = 0; i < operationsToArray.Length; i++)
|
||||
{
|
||||
var row = sheet.Row(1 + i + DefaultTemplateInfo.HeaderRowsCount);
|
||||
AddOperationToRow(row, operationsToArray[i], sections, categories);
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddOperationToRow(IXLRow row, WellOperationDto operation, IEnumerable<WellSectionTypeDto> sections,
|
||||
IEnumerable<WellOperationCategoryDto> categories)
|
||||
{
|
||||
var sectionCaption = sections.First(s => s.Id == operation.IdWellSectionType).Caption;
|
||||
var categoryName = categories.First(o => o.Id == operation.IdCategory).Name;
|
||||
|
||||
row.Cell(DefaultTemplateInfo.ColumnSection).SetCellValue(sectionCaption);
|
||||
row.Cell(DefaultTemplateInfo.ColumnCategory).SetCellValue(categoryName);
|
||||
row.Cell(DefaultTemplateInfo.ColumnCategoryInfo).SetCellValue(operation.CategoryInfo);
|
||||
row.Cell(DefaultTemplateInfo.ColumnDepthStart).SetCellValue(operation.DepthStart);
|
||||
row.Cell(DefaultTemplateInfo.ColumnDepthEnd).SetCellValue(operation.DepthEnd);
|
||||
row.Cell(DefaultTemplateInfo.ColumnDate).SetCellValue(operation.DateStart.DateTime);
|
||||
row.Cell(DefaultTemplateInfo.ColumnDuration).SetCellValue(operation.DurationHours);
|
||||
row.Cell(DefaultTemplateInfo.ColumnComment).SetCellValue(operation.Comment);
|
||||
}
|
||||
}
|
@ -1,119 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using AsbCloudApp.Data;
|
||||
using AsbCloudApp.Data.WellOperationImport;
|
||||
using AsbCloudApp.Repositories;
|
||||
using AsbCloudApp.Services;
|
||||
using AsbCloudApp.Services.WellOperationImport;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services.WellOperationImport;
|
||||
|
||||
public class WellOperationImportService : IWellOperationImportService
|
||||
{
|
||||
private readonly IWellService wellService;
|
||||
private readonly IWellOperationRepository wellOperationRepository;
|
||||
private readonly IWellOperationCategoryRepository wellOperationCategoryRepository;
|
||||
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(
|
||||
IWellService wellService,
|
||||
IWellOperationRepository wellOperationRepository,
|
||||
IWellOperationCategoryRepository wellOperationCategoryRepository
|
||||
)
|
||||
{
|
||||
this.wellService = wellService;
|
||||
this.wellOperationRepository = wellOperationRepository;
|
||||
this.wellOperationCategoryRepository = wellOperationCategoryRepository;
|
||||
}
|
||||
|
||||
public IEnumerable<WellOperationDto> Import(int idWell, int idUser, int idType, SheetDto sheet)
|
||||
{
|
||||
var validationErrors = new List<string>();
|
||||
|
||||
var sections = wellOperationRepository.GetSectionTypes();
|
||||
var categories = wellOperationCategoryRepository.Get(false);
|
||||
|
||||
var wellOperations = new List<WellOperationDto>();
|
||||
|
||||
var rows = sheet.Rows.OrderBy(r => r.Date);
|
||||
|
||||
var prevRow = new RowDto();
|
||||
|
||||
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($"Лист '{sheet.Name}'. В строке '{row.Number}' не удалось определить секцию");
|
||||
|
||||
var category = categories.FirstOrDefault(c =>
|
||||
string.Equals(c.Name, row.Category, StringComparison.CurrentCultureIgnoreCase));
|
||||
|
||||
if (category is null)
|
||||
throw new FileFormatException($"Лист '{sheet.Name}'. В строке '{row.Number}' не удалось определить операцию");
|
||||
|
||||
if (row.DepthStart is not (>= 0d and <= 20_000d))
|
||||
throw new FileFormatException(
|
||||
$"Лист '{sheet.Name}'. Строка '{row.Number}' некорректная глубина на начало операции");
|
||||
|
||||
if (row.DepthEnd is not (>= 0d and <= 20_000d))
|
||||
throw new FileFormatException(
|
||||
$"Лист '{sheet.Name}'. Строка '{row.Number}' некорректная глубина на конец операции");
|
||||
|
||||
if (row.Date < dateLimitMin && row.Date > dateLimitMax)
|
||||
throw new FileFormatException(
|
||||
$"Лист '{sheet.Name}'. Строка '{row.Number}' неправильно получена дата начала операции");
|
||||
|
||||
if (prevRow.Date > row.Date)
|
||||
throw new FileFormatException(
|
||||
$"Лист '{sheet.Name}' строка '{row.Number}' дата позднее даты предыдущей операции");
|
||||
|
||||
if (row.Duration is not (>= 0d and <= 240d))
|
||||
throw new FileFormatException($"Лист '{sheet.Name}'. Строка '{row.Number}' некорректная длительность операции");
|
||||
|
||||
var timezone = wellService.GetTimezone(idWell);
|
||||
var timezoneOffset = TimeSpan.FromHours(timezone.Hours);
|
||||
|
||||
var wellOperation = new WellOperationDto
|
||||
{
|
||||
IdWell = idWell,
|
||||
IdUser = idUser,
|
||||
IdType = idType,
|
||||
IdWellSectionType = section.Id,
|
||||
WellSectionTypeName = section.Caption,
|
||||
IdCategory = category.Id,
|
||||
CategoryName = category.Name,
|
||||
CategoryInfo = row.CategoryInfo,
|
||||
DepthStart = row.DepthStart,
|
||||
DepthEnd = row.DepthEnd,
|
||||
DateStart = new DateTimeOffset(row.Date, timezoneOffset),
|
||||
DurationHours = row.Duration,
|
||||
Comment = row.Comment
|
||||
};
|
||||
|
||||
wellOperations.Add(wellOperation);
|
||||
|
||||
prevRow = row;
|
||||
}
|
||||
catch (FileFormatException ex)
|
||||
{
|
||||
validationErrors.Add(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
if (wellOperations.Any() && wellOperations.Min(o => o.DateStart) - wellOperations.Max(o => o.DateStart) > drillingDurationLimitMax)
|
||||
validationErrors.Add($"Лист {sheet.Name} содержит диапазон дат больше {drillingDurationLimitMax}");
|
||||
|
||||
if (validationErrors.Any())
|
||||
throw new FileFormatException(string.Join("\r\n", validationErrors));
|
||||
|
||||
return wellOperations;
|
||||
}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using AsbCloudApp.Services.WellOperationImport;
|
||||
|
||||
namespace AsbCloudInfrastructure.Services.WellOperationImport;
|
||||
|
||||
public class WellOperationImportTemplateService : IWellOperationImportTemplateService
|
||||
{
|
||||
public Stream GetExcelTemplateStream()
|
||||
{
|
||||
var resourceName = Assembly.GetExecutingAssembly()
|
||||
.GetManifestResourceNames()
|
||||
.FirstOrDefault(n => n.EndsWith("WellOperationImportTemplate.xlsx"))!;
|
||||
|
||||
var stream = Assembly.GetExecutingAssembly()
|
||||
.GetManifestResourceStream(resourceName)!;
|
||||
|
||||
return stream;
|
||||
}
|
||||
}
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user