DD.WellWorkover.Cloud/AsbCloudInfrastructure/Services/DailyReportService.cs
zikan 019c6a4db1 - Added t_daily_report table and related migrations;
- Added request processing service for DailyReportController. Implemented all methods except DownloadAsync.
2022-04-26 16:45:52 +05:00

338 lines
12 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using AsbCloudApp.Data;
using AsbCloudApp.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudDb.Model;
using AsbCloudInfrastructure.Services.Cache;
using AsbCloudApp.Exceptions;
using Mapster;
using Microsoft.EntityFrameworkCore;
using System.Collections;
using System.IO;
using ClosedXML.Excel;
namespace AsbCloudInfrastructure.Services
{
public class DailyReportService : IDailyReportService
{
private readonly IAsbCloudDbContext db;
private readonly IWellService wellService;
private readonly IOperationsStatService operationsStatService;
const string sheetNameSchedule = "Дневной отчёт";
private static readonly int[,] ParamsCellsIndexes = new int[42, 2] {
{0,0},
{1,1},
{1,1},
{1,1},
{1,1},
{1,1},
{1,1},
{1,1},
{1,1},
{1,1},
{1,1},
{1,1},
{1,1},
{1,1},
{1,1},
{1,1},
{1,1},
{1,1},
{1,1},
{1,1},
{1,1},
{1,1},
{1,1},
{1,1},
{1,1},
{1,1},
{1,1},
{1,1},
{1,1},
{1,1},
{1,1},
{1,1},
{1,1},
{1,1},
{1,1},
{1,1},
{1,1},
{1,1},
{1,1},
{1,1},
{1,1},
{1,1}
};
public DailyReportService(IAsbCloudDbContext db, IWellService wellService)
{
this.db = db;
this.wellService = wellService;
}
private DateTimeOffset Convert(DateTime date, int idWell)
{
var hours = wellService.GetTimezone(idWell).Hours;
var dateOffset = DateTimeExtentions.ToUtcDateTimeOffset((DateTime)date, hours);
return dateOffset;
}
private DailyReportDto Convert(DailyReport data, int idWell)
{
var hours = wellService.GetTimezone(idWell).Hours;
var dto = data.Adapt<DailyReportDto>();
dto.ReportDate = data.StartDate.ToRemoteDateTime(hours);
return dto;
}
private static Stream GetExcelTemplateStream()
{
var assembly = System.Reflection.Assembly.GetAssembly(typeof(AsbCloudInfrastructure.IInfrastructureMarker));
var stream = assembly.GetManifestResourceStream("AsbCloudInfrastructure.Services.DailyReport.DailyReportTemplate.xlsx");
return stream;
}
public async Task<IEnumerable<DailyReportDto>> GetListAsync(int idWell, DateTime? begin, DateTime? end, CancellationToken token)
{
var hours = wellService.GetTimezone(idWell).Hours;
var query = db.DailyReport.Where(r => r.IdWell == idWell);
if (begin is not null)
query = query.Where(d => d.StartDate >= Convert((DateTime)begin, idWell));
if (end is not null)
query = query.Where(d => d.StartDate <= Convert((DateTime)end, idWell));
var data = await query.ToListAsync(token);
return data.Select(d=>Convert(d, idWell));
}
public IEnumerable<DailyReportDto> GetDefaultDailyReportDto()
{
var dto = new DailyReportDto()
{
ReportDate = DateTime.Now,
};
IEnumerable<DailyReportDto> result = new List<DailyReportDto> { dto };
return result;
}
public async Task<IEnumerable<DailyReportDto>> GetOrGenerateAsync(int idWell, DateTime date, CancellationToken token)
{
var query = db.DailyReport.Where(r => r.IdWell == idWell);
query = query.Where(d => d.StartDate == Convert(date, idWell));
var data = await query.ToListAsync(token);
if (data.Count == 0)
return GetDefaultDailyReportDto();
else
return data.Select(d => Convert(d, idWell));
}
public async Task<int> AddAsync(int idWell, DailyReportDto dto, CancellationToken token = default)
{
var entity = dto.Adapt<DailyReport>();
entity.StartDate = Convert(dto.ReportDate, idWell);
db.DailyReport.Add(entity);
var result = await db.SaveChangesAsync(token);
return result;
}
public async Task<int> UpdateAsync(int idWell, DateTime date, DailyReportDto dto, CancellationToken token)
{
var entity = dto.Adapt<DailyReport>();
entity.StartDate = Convert(dto.ReportDate, idWell);
db.DailyReport.Update(entity);
var result = await db.SaveChangesAsync(token);
return result;
}
public async Task<Stream> MakeReportAsync(int idWell, DateTime date, CancellationToken token = default)
{
var tvd = await operationsStatService.GetTvdAsync(idWell, token);
if (!tvd.Any())
return null;
var well = await wellService.GetAsync(idWell, token);
var ecxelTemplateStream = GetExcelTemplateStream();
using var workbook = new XLWorkbook(ecxelTemplateStream, XLEventTracking.Disabled);
FillScheduleSheetToWorkbook(workbook, tvd, well);
FillTvdSheetToWorkbook(workbook, tvd, well);
MemoryStream memoryStream = new MemoryStream();
workbook.SaveAs(memoryStream, new SaveOptions { });
memoryStream.Seek(0, SeekOrigin.Begin);
return memoryStream;
}
private static void FillScheduleSheetToWorkbook(XLWorkbook workbook, IEnumerable<PlanFactPredictBase<WellOperationDto>> tvd, WellDto well)
{
var sheet = workbook.Worksheets.FirstOrDefault(ws => ws.Name == sheetNameSchedule);
if (sheet is null)
return;
const int headerRowsCount = 6;
const int rowTitle = 3;
const int columnRowNumber = 2;
const int columnCaption = 3;
const int columnWellDepthStartPlan = 4;
const int columnWellDepthStartFact = 5;
const int columnWellDepthStartPredict = 6;
const int columnWellDepthEndPlan = 7;
const int columnWellDepthEndFact = 8;
const int columnWellDepthEndPredict = 9;
const int columnDeltaWellDepthPerDay = 10;
const int columnDurationPlan = 11;
const int columnDurationFact = 12;
const int columnDurationPredict = 13;
const int columnDateStartPlan = 14;
const int columnDateStartFact = 15;
const int columnDateStartPredict = 16;
const int columnDateEndPlan = 17;
const int columnDateEndFact = 18;
const int columnDateEndPredict = 19;
const int columnGuilty = 20;
const int columnNpt = 21;
var subTitle = $"на строительство скважины №{well.Caption}, куст: {well.Cluster}, м/р: {well.Deposit}";
sheet.Row(rowTitle).Cell(3).Value = subTitle;
var tvdList = tvd.ToList();
}
private static void FillTvdSheetToWorkbook(XLWorkbook workbook, IEnumerable<PlanFactPredictBase<WellOperationDto>> tvd, WellDto well)
{
var sheet = workbook.Worksheets.FirstOrDefault(ws => ws.Name == sheetNameTvd);
if (sheet is null)
return;
const int rowTitle = 2;
const int rowSubtitle = 3;
const int colTitle = 5;
const int rowTopStatTitle = 2;
const int colTopStatvalue = 10;
const int colBottomStatvalue = 3;
const int rowStartDateFact = 43;
const int rowEndDatePlan = 44;
const int rowEndDateFact = 45;
sheet.Row(rowSubtitle).Cell(colTitle).Value
= $"скважины №{well.Caption}, куст: {well.Cluster}, м/р: {well.Deposit}";
SetCell(sheet.Row(rowTitle), colTopStatvalue, DateTime.Now);
var Plan = tvd.Where(t => t.Plan is not null)
.Select(t => t.Plan);
var Fact = tvd.Where(t => t.Fact is not null)
.Select(t => t.Fact);
var Predict = tvd.Where(t => t.Predict is not null)
.Select(t => t.Predict);
var startDateFact = Fact.FirstOrDefault()?.DateStart;
var planLast = Plan.LastOrDefault();
var factLast = Fact.LastOrDefault();
var predictLast = Predict.LastOrDefault();
static DateTime GetEndDate(WellOperationDto operation)
=> operation is not null
? operation.DateStart.AddHours(operation.DurationHours)
: default;
var endDatePlan = GetEndDate(planLast);
var endDateFact = GetEndDate(factLast);
var endDatePredict = GetEndDate(predictLast);
var endDate = endDatePredict > endDateFact
? endDatePredict
: endDateFact;
if (startDateFact is not null)
{
SetCell(sheet.Row(rowStartDateFact), colBottomStatvalue, startDateFact);
SetCell(sheet.Row(rowEndDatePlan), colBottomStatvalue, endDatePlan);
SetCell(sheet.Row(rowEndDateFact), colBottomStatvalue, endDate);
if (endDate != default)
{
var deltaEndDate = (endDatePlan - endDate).TotalDays;
SetCell(sheet.Row(rowTopStatTitle + 1), colTopStatvalue, Math.Abs(deltaEndDate));
if (deltaEndDate >= 0)
SetCell(sheet.Row(rowTopStatTitle + 1), colTopStatvalue - 1, "+")
.Style.Font.SetFontColor(XLColor.Green);
else
SetCell(sheet.Row(rowTopStatTitle + 1), colTopStatvalue - 1, "—")
.Style.Font.SetFontColor(XLColor.Red);
}
}
}
private static string GetColunmLetter(int columnNumber)
{
string letter = "";
while (columnNumber > 0)
{
int modulo = (columnNumber - 1) % 26;
letter = Convert.ToChar('A' + modulo) + letter;
columnNumber = (columnNumber - modulo) / 26;
}
return letter;
}
private static IXLStyle SetBorder(IXLStyle style)
{
style.Border.RightBorder = XLBorderStyleValues.Thin;
style.Border.LeftBorder = XLBorderStyleValues.Thin;
style.Border.TopBorder = XLBorderStyleValues.Thin;
style.Border.BottomBorder = XLBorderStyleValues.Thin;
style.Border.InsideBorder = XLBorderStyleValues.Thin;
return style;
}
private static IXLCell SetDateTime(IXLCell cell)
{
cell.DataType = XLDataType.DateTime;
cell.Style.DateFormat.Format = "DD.MM.YYYY HH:MM:SS";
return cell;
}
private static IXLCell SetNumber(IXLCell cell)
{
cell.DataType = XLDataType.Number;
cell.Style.NumberFormat.Format = "0.00";
return cell;
}
private static IXLCell SetCell(IXLRow row, int colunm, object value)
{
var cell = row.Cell(colunm);
cell.Value = value;
SetBorder(cell.Style);
cell.Style.Alignment.WrapText = true;
if (value is string valueString && valueString.Length > maxChartsToWrap)
{
var baseHeight = row.Height;
row.Height = 0.82d * baseHeight * Math.Ceiling(1d + valueString.Length / maxChartsToWrap);
}
if (value is DateTime)
{
SetDateTime(cell);
}
else if (value is IFormattable)
{
SetNumber(cell);
}
return cell;
}
}
}