DD.WellWorkover.Cloud/AsbCloudInfrastructure/Services/PlannedTrajectoryService/PlannedTrajectoryImportService.cs
2022-12-25 23:16:36 +05:00

259 lines
12 KiB
C#

using AsbCloudApp.Data;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using ClosedXML.Excel;
using Mapster;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace AsbCloudInfrastructure.Services.PlannedTrajectory
{
#nullable enable
public class PlannedTrajectoryImportService : IPlannedTrajectoryImportService
{
/*
* password for PlannedTrajectoryTemplate.xlsx is Drill2022
*/
private readonly IAsbCloudDbContext db;
private readonly IWellService wellService;
private const string sheetNamePlannedTrajectory = "Плановая траектория";
private const int headerRowsCount = 2;
private const int ColumnWellboreDepth = 1;
private const int ColumnZenithAngle = 2;
private const int ColumnAzimuthGeo = 3;
private const int ColumnAzimuthMagnetic = 4;
private const int ColumnVerticalDepth = 5;
private const int ColumnAbsoluteMark = 6;
private const int ColumnNorthOrifice = 7;
private const int ColumnEastOrifice = 8;
private const int ColumnEastCartographic = 9;
private const int ColumnNorthCartographic = 10;
private const int ColumnSpatialIntensity = 11;
private const int ColumnAngleIntensity = 12;
private const int ColumnAzimuthIntensity = 13;
private const int ColumnOrificeOffset = 14;
private const int ColumnComment = 15;
public PlannedTrajectoryImportService(IAsbCloudDbContext db, IWellService wellService)
{
this.db = db;
this.wellService = wellService;
}
public Stream GetTemplateFile()
{
var stream = System.Reflection.Assembly.GetExecutingAssembly()
.GetManifestResourceStream("AsbCloudInfrastructure.Services.PlannedTrajectoryService.PlannedTrajectoryTemplate.xlsx");
return stream;
}
public Stream Export(int idWell)
{
var plannedTrajectorys = db.PlannedTrajectorys
.Where(o => o.IdWell == idWell)
.AsNoTracking()
.ToList();
if (!plannedTrajectorys.Any())
return null;
var timezone = wellService.GetTimezone(idWell);
return MakeExelFileStream(plannedTrajectorys);
}
private Stream MakeExelFileStream(IEnumerable<AsbCloudDb.Model.PlannedTrajectory> plannedTrajectories)
{
using Stream ecxelTemplateStream = GetTemplateFile();
using var workbook = new XLWorkbook(ecxelTemplateStream, XLEventTracking.Disabled);
AddOperationsToWorkbook(workbook, plannedTrajectories);
MemoryStream memoryStream = new MemoryStream();
workbook.SaveAs(memoryStream, new SaveOptions { });
memoryStream.Seek(0, SeekOrigin.Begin);
return memoryStream;
}
private static void AddOperationsToWorkbook(XLWorkbook workbook, IEnumerable<AsbCloudDb.Model.PlannedTrajectory> plannedTrajectories)
{
if (plannedTrajectories.Any())
{
var sheet = workbook.Worksheets.FirstOrDefault(ws => ws.Name == sheetNamePlannedTrajectory);
AddOperationsToSheet(sheet, plannedTrajectories);
}
}
private static void AddOperationsToSheet(IXLWorksheet sheet, IEnumerable<AsbCloudDb.Model.PlannedTrajectory> plannedTrajectories)
{
var operationsList = plannedTrajectories.ToList();
for (int i = 0; i < operationsList.Count; i++)
{
var row = sheet.Row(1 + i + headerRowsCount);
AddOperationToRow(row, operationsList[i]);
}
}
private static void AddOperationToRow(IXLRow row, AsbCloudDb.Model.PlannedTrajectory trajectory)
{
row.Cell(ColumnWellboreDepth).Value = trajectory.WellboreDepth;
row.Cell(ColumnZenithAngle).Value = trajectory.ZenithAngle;
row.Cell(ColumnAzimuthGeo).Value = trajectory.AzimuthGeo;
row.Cell(ColumnAzimuthMagnetic).Value = trajectory.AzimuthMagnetic;
row.Cell(ColumnVerticalDepth).Value = trajectory.VerticalDepth;
row.Cell(ColumnAbsoluteMark).Value = trajectory.AbsoluteMark;
row.Cell(ColumnNorthOrifice).Value = trajectory.NorthOrifice;
row.Cell(ColumnEastOrifice).Value = trajectory.EastOrifice;
row.Cell(ColumnEastCartographic).Value = trajectory.EastCartographic;
row.Cell(ColumnNorthCartographic).Value = trajectory.NorthCartographic;
row.Cell(ColumnSpatialIntensity).Value = trajectory.SpatialIntensity;
row.Cell(ColumnAngleIntensity).Value = trajectory.AngleIntensity;
row.Cell(ColumnAzimuthIntensity).Value = trajectory.AzimuthIntensity;
row.Cell(ColumnOrificeOffset).Value = trajectory.OrificeOffset;
row.Cell(ColumnComment).Value = trajectory.Comment;
}
public void Import(int idWell, int idUser, Stream stream, bool deletePrevRows = false)
{
using var workbook = new XLWorkbook(stream, XLEventTracking.Disabled);
var trajectoryRows = ParseFileStream(stream);
foreach (var row in trajectoryRows)
row.IdWell = idWell;
SaveOperations(idWell, idUser, trajectoryRows, deletePrevRows);
}
private void SaveOperations(int idWell, int idUser, IEnumerable<PlannedTrajectoryDto> newRows, bool deletePrevRow = false)
{
var timezone = wellService.GetTimezone(idWell);
var transaction = db.Database.BeginTransaction();
try
{
if (deletePrevRow)
db.WellOperations.RemoveRange(db.WellOperations.Where(o => o.IdWell == idWell));
var entities = newRows.Select(o =>
{
var entity = o.Adapt<AsbCloudDb.Model.PlannedTrajectory>();
entity.IdWell = idWell;
entity.LoadDate = DateTime.Today.ToUtcDateTimeOffset(timezone.Hours);
entity.IdUser = idUser;
return entity;
});
db.PlannedTrajectorys.AddRange(entities);
db.SaveChanges();
transaction.Commit();
}
catch
{
transaction.Rollback();
throw;
}
}
private IEnumerable<PlannedTrajectoryDto> ParseFileStream(Stream stream)
{
using var workbook = new XLWorkbook(stream, XLEventTracking.Disabled);
return ParseWorkbook(workbook);
}
private IEnumerable<PlannedTrajectoryDto> ParseWorkbook(IXLWorkbook workbook)
{
var sheetPlannedTrajectory = workbook.Worksheets.FirstOrDefault(ws => ws.Name == sheetNamePlannedTrajectory);
if (sheetPlannedTrajectory is null)
throw new FileFormatException($"Книга excel не содержит листа {sheetNamePlannedTrajectory}.");
var plannedTrajectoryRows = ParseSheet(sheetPlannedTrajectory);
return plannedTrajectoryRows;
}
private IEnumerable<PlannedTrajectoryDto> ParseSheet(IXLWorksheet sheet)
{
if (sheet.RangeUsed().RangeAddress.LastAddress.ColumnNumber < 15)
throw new FileFormatException($"Лист {sheet.Name} содержит меньшее количество столбцов.");
var count = sheet.RowsUsed().Count() - headerRowsCount;
if (count > 1024)
throw new FileFormatException($"Лист {sheet.Name} содержит слишком большое количество операций.");
if (count <= 0)
throw new FileFormatException($"Лист {sheet.Name} некорректного формата либо пустой");
var trajectoryRows = new List<PlannedTrajectoryDto>(count);
var parseErrors = new List<string>();
for (int i = 0; i < count; i++)
{
var row = sheet.Row(1 + i + headerRowsCount);
try
{
var trajectoryRow = ParseRow(row);
trajectoryRows.Add(trajectoryRow);
}
catch (FileFormatException ex)
{
parseErrors.Add(ex.Message);
}
};
return trajectoryRows;
}
private PlannedTrajectoryDto ParseRow(IXLRow row)
{
var _wellboreDepth = row.Cell(ColumnWellboreDepth).Value;
var _zenithAngle = row.Cell(ColumnZenithAngle).Value;
var _azimuthGeo = row.Cell(ColumnAzimuthGeo).Value;
var _azimuthMagnetic = row.Cell(ColumnAzimuthMagnetic).Value;
var _verticalDepth = row.Cell(ColumnVerticalDepth).Value;
var _absoluteMark = row.Cell(ColumnAbsoluteMark).Value;
var _northOrifice = row.Cell(ColumnNorthOrifice).Value;
var _eastOrifice = row.Cell(ColumnEastOrifice).Value;
var _eastCartographic = row.Cell(ColumnEastCartographic).Value;
var _northCartographic = row.Cell(ColumnNorthCartographic).Value;
var _spatialIntensity = row.Cell(ColumnSpatialIntensity).Value;
var _angleIntensity = row.Cell(ColumnAngleIntensity).Value;
var _azimuthIntensity = row.Cell(ColumnAzimuthIntensity).Value;
var _orificeOffset = row.Cell(ColumnOrificeOffset).Value;
var _comment = row.Cell(ColumnComment).Value;
var trajectoryRow = new PlannedTrajectoryDto();
static bool isCorrectValue(object value)
{
if (value is null)
return true;
if (value is double)
return true;
return false;
}
static double? getDoubleValue(object value, string nameParam, IXLRow row)
{
if (!isCorrectValue(value))
throw new FileFormatException($"Лист {row.Worksheet.Name}. Строка {row.RowNumber()} - некорректные данные - {nameParam}");
if (value is double _value)
return _value;
return null;
}
trajectoryRow.WellboreDepth = getDoubleValue(_wellboreDepth, "Глубина по стволу", row);
trajectoryRow.ZenithAngle = getDoubleValue(_zenithAngle, "Зенитный угол", row);
trajectoryRow.AzimuthGeo = getDoubleValue(_azimuthGeo, "Азимут географический", row);
trajectoryRow.AzimuthMagnetic = getDoubleValue(_azimuthMagnetic, "Азимут магнитный", row);
trajectoryRow.VerticalDepth = getDoubleValue(_verticalDepth, "Глубина вертикальная", row);
trajectoryRow.AbsoluteMark = getDoubleValue(_absoluteMark, "Абсолютная отметка", row);
trajectoryRow.NorthOrifice = getDoubleValue(_northOrifice, "Север относительно устья", row);
trajectoryRow.EastOrifice = getDoubleValue(_eastOrifice, "Восток относительно устья", row);
trajectoryRow.EastCartographic = getDoubleValue(_eastCartographic, "Восток картографический", row);
trajectoryRow.NorthCartographic = getDoubleValue(_northCartographic, "Север картографический", row);
trajectoryRow.SpatialIntensity = getDoubleValue(_spatialIntensity, "Простр. интенсивность", row);
trajectoryRow.AngleIntensity = getDoubleValue(_angleIntensity, "Интенсивность по углу", row);
trajectoryRow.AzimuthIntensity = getDoubleValue(_azimuthIntensity, "Интенсивность по азимуту", row);
trajectoryRow.OrificeOffset = getDoubleValue(_orificeOffset, "Смещение от устья", row);
if (_comment is not null)
trajectoryRow.Comment = _comment.ToString();
return trajectoryRow;
}
}
#nullable disable
}