using AsbCloudApp.Data.DailyReport; using AsbCloudApp.Exceptions; using AsbCloudApp.Services; using AsbCloudDb.Model; using AsbCloudDb.Model.DailyReport; using Mapster; using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace AsbCloudInfrastructure.Services.DailyReport { #nullable enable public class DailyReportService : IDailyReportService { private readonly IAsbCloudDbContext db; private readonly IWellService wellService; private readonly DailyReportMakerExcel dailyReportMaker = new DailyReportMakerExcel(); public DailyReportService(IAsbCloudDbContext db, IWellService wellService) { this.db = db; this.wellService = wellService; } public async Task> GetListAsync(int idWell, DateTime? begin, DateTime? end, CancellationToken token) { var well = wellService.GetOrDefault(idWell); if (well is null || well.Timezone is null) throw new ArgumentInvalidException("idWell doesn`t exist", nameof(idWell)); var query = db.DailyReports.Where(r => r.IdWell == idWell); DateOnly ExtractDate(DateTime dateTime) { var dateTimeOffset = dateTime.ToUtcDateTimeOffset(well!.Timezone.Hours); var date = new DateOnly(dateTimeOffset.Year, dateTimeOffset.Month, dateTimeOffset.Day); return date; } if (begin is not null) { var beginDateOnly = ExtractDate(begin.Value); query = query.Where(d => d.StartDate >= beginDateOnly); } if (end is not null) { var endDateOnly = ExtractDate(end.Value); query = query.Where(d => d.StartDate <= endDateOnly); } var entities = await query .OrderByDescending(e => e.StartDate) .ToListAsync(token); return entities.Select(r => Convert(r)); } public async Task GetOrGenerateAsync(int idWell, DateTime date, CancellationToken token) { var dateOnly = DateTime.SpecifyKind(date.Date, DateTimeKind.Utc); var dailyReportDto = await GetOrDefaultAsync(idWell, dateOnly, token); dailyReportDto ??= await MakeDefaultDailyReportAsync(idWell, dateOnly, token); return dailyReportDto; } public async Task AddAsync(int idWell, DateTime startDate, CancellationToken token = default) { var well = wellService.GetOrDefault(idWell); if (well is null || well.Timezone is null) throw new ArgumentInvalidException("idWell doesn`t exist", nameof(idWell)); var startDateOnly = DateOnly.FromDateTime(startDate); var entity = await db.DailyReports .FirstOrDefaultAsync(r => r.IdWell == idWell && r.StartDate == startDateOnly, token); if (entity is not null) throw new Exception($"daily report on {startDateOnly} already exists"); var customer = well.Companies.FirstOrDefault(company => company.IdCompanyType == 1); var contractor = well.Companies.FirstOrDefault(company => company.IdCompanyType == 2); entity = new AsbCloudDb.Model.DailyReport.DailyReport { IdWell = idWell, StartDate = startDateOnly, Info = new DailyReportInfo() { Head = new Head() { ReportDate = startDate.Date, WellName = well.Caption, ClusterName = well?.Cluster ?? String.Empty, Customer = customer?.Caption ?? String.Empty, Contractor = contractor?.Caption ?? String.Empty, } } }; db.DailyReports.Add(entity); var result = await db.SaveChangesAsync(token); return result; } public async Task UpdateAsync(int idWell, DateTime date, DailyReportDto dto, CancellationToken token) { var dateOffset = date.Date; var entity = await db.DailyReports .FirstOrDefaultAsync(r => r.IdWell == idWell && r.StartDate.Year == dateOffset.Year && r.StartDate.DayOfYear == dateOffset.DayOfYear , token); if (entity is null) return 0; entity.Info = Convert(dto); db.DailyReports.Update(entity); var result = await db.SaveChangesAsync(token); return result; } public async Task UpdateBlockAsync(int idWell, DateTime date, Tdto dto, CancellationToken token) { var startDateOnly = DateOnly.FromDateTime(date); var entity = await db.DailyReports.FirstOrDefaultAsync(r => r.IdWell == idWell && r.StartDate == startDateOnly, token); if (entity is null) return 0; if (dto is HeadDto headDto) entity.Info.Head = headDto.Adapt(); if (dto is BhaDto bhaDto) entity.Info.Bha = bhaDto.Adapt(); if (dto is NoDrillingDto noDrillingDto) entity.Info.NoDrilling = noDrillingDto.Adapt(); if (dto is TimeBalanceDto timeBalanceDto) entity.Info.TimeBalance = timeBalanceDto.Adapt(); if (dto is SaubDto saubDto) entity.Info.Saub = saubDto.Adapt(); if (dto is SignDto signDto) entity.Info.Sign = signDto.Adapt(); db.DailyReports.Update(entity); var result = await db.SaveChangesAsync(token); return result; } public async Task MakeReportAsync(int idWell, DateTime date, CancellationToken token = default) { var dailyReportDto = await GetOrDefaultAsync(idWell, date, token); if (dailyReportDto is null) return null; var memoryStream = dailyReportMaker.MakeReportFromBlocks(dailyReportDto); return memoryStream; } private async Task GetOrDefaultAsync(int idWell, DateTime date, CancellationToken token) { var dateOffset = date.Date; var entity = await db.DailyReports .FirstOrDefaultAsync(r => r.IdWell == idWell && r.StartDate.Year == dateOffset.Year && r.StartDate.DayOfYear == dateOffset.DayOfYear , token); if (entity is null) return null; var dto = Convert(entity); return dto; } private async Task MakeDefaultDailyReportAsync(int idWell, DateTime date, CancellationToken token) { var well = await wellService.GetOrDefaultAsync(idWell, token); var dto = new DailyReportDto() { Head = new HeadDto() { ReportDate = date.Date, WellName = well?.Caption ?? "", ClusterName = well?.Cluster ?? "", }, Bha = await GetPrevOrNewBhaAsync(idWell, date, token) }; return dto; } private async Task GetPrevOrNewBhaAsync(int idWell, DateTime date, CancellationToken token) { var dateOffset = date.Date; var entity = await db.DailyReports .Where(x => x.IdWell == idWell) .OrderByDescending(x => x.StartDate) .FirstOrDefaultAsync(r => r.StartDate.Year <= dateOffset.Year && r.StartDate.DayOfYear <= dateOffset.DayOfYear, token); if (entity is null) return new BhaDto(); var dto = Convert(entity); return dto.Bha; } private static DailyReportDto Convert(AsbCloudDb.Model.DailyReport.DailyReport entity) { var dto = entity.Info.Adapt(); dto.StartDate = entity.StartDate; return dto; } private static DailyReportInfo Convert(DailyReportDto dto) { var entity = dto.Adapt(); entity.Head.ReportDate = dto.Head.ReportDate.Date.Date; return entity; } } #nullable disable }