forked from ddrilling/AsbCloudServer
249 lines
10 KiB
C#
249 lines
10 KiB
C#
using AsbCloudApp.Data;
|
|
using AsbCloudApp.Data.DailyReport;
|
|
using AsbCloudApp.Exceptions;
|
|
using AsbCloudApp.Repositories;
|
|
using AsbCloudApp.Requests;
|
|
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 IUserRepository userRepository;
|
|
private readonly IWellOperationRepository wellOperationRepository;
|
|
private readonly IWellService wellService;
|
|
private readonly DailyReportMakerExcel dailyReportMaker = new DailyReportMakerExcel();
|
|
|
|
public DailyReportService(
|
|
IAsbCloudDbContext db,
|
|
IWellService wellService,
|
|
IUserRepository userRepository,
|
|
IWellOperationRepository wellOperationRepository)
|
|
{
|
|
this.db = db;
|
|
this.wellService = wellService;
|
|
this.userRepository = userRepository;
|
|
this.wellOperationRepository = wellOperationRepository;
|
|
|
|
}
|
|
|
|
public async Task<IEnumerable<DailyReportDto>> GetListAsync(int idWell, DateOnly? begin, DateOnly? 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);
|
|
|
|
if (begin is not null)
|
|
{
|
|
query = query.Where(d => d.StartDate >= begin);
|
|
}
|
|
|
|
if (end is not null)
|
|
{
|
|
query = query.Where(d => d.StartDate <= end);
|
|
}
|
|
|
|
var entities = await query.OrderByDescending(e => e.StartDate)
|
|
.AsNoTracking()
|
|
.ToArrayAsync(token)
|
|
.ConfigureAwait(false);
|
|
|
|
var factOperationsForDtos = await GetFactOperationsForDailyReportAsync(idWell, token);
|
|
var userDtos = await userRepository.GetAllAsync(token);
|
|
|
|
var dtos = entities.Select(entity => Convert(entity, factOperationsForDtos, userDtos));
|
|
return dtos;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Получение фактических операций для суточного рапорта
|
|
/// </summary>
|
|
/// <param name="idWell"></param>
|
|
/// <param name="token"></param>
|
|
/// <returns></returns>
|
|
private async Task<IEnumerable<WellOperationDto>> GetFactOperationsForDailyReportAsync(int idWell, CancellationToken token)
|
|
{
|
|
var request = new WellOperationRequest()
|
|
{
|
|
IdWell = idWell,
|
|
OperationType = WellOperation.IdOperationTypeFact,
|
|
};
|
|
|
|
var factOperations = await wellOperationRepository.GetAsync(request, token);
|
|
return factOperations;
|
|
}
|
|
|
|
public async Task<int> AddAsync(int idWell, DateOnly startDate, int idUser, CancellationToken token)
|
|
{
|
|
var well = wellService.GetOrDefault(idWell);
|
|
if (well is null)
|
|
throw new ArgumentInvalidException("idWell doesn`t exist", nameof(idWell));
|
|
|
|
|
|
var hasEntity = await db.DailyReports
|
|
.AnyAsync(r => r.IdWell == idWell && r.StartDate == startDate, token);
|
|
if (hasEntity)
|
|
throw new ArgumentInvalidException($"daily report on {startDate} already exists", nameof(startDate));
|
|
|
|
var entity = new AsbCloudDb.Model.DailyReport.DailyReport
|
|
{
|
|
IdWell = idWell,
|
|
StartDate = startDate,
|
|
Info = new DailyReportInfo()
|
|
{
|
|
Head = CreateHeadDailyReportBlock(well, startDate, idUser)
|
|
}
|
|
};
|
|
db.DailyReports.Add(entity);
|
|
var result = await db.SaveChangesAsync(token);
|
|
return result;
|
|
}
|
|
|
|
public async Task<int> UpdateBlockAsync(int idWell, DateOnly startDate, ItemInfoDto dto, CancellationToken token)
|
|
{
|
|
var well = wellService.GetOrDefault(idWell);
|
|
if (well is null)
|
|
throw new ArgumentInvalidException("idWell doesn`t exist", nameof(idWell));
|
|
|
|
var entity = await db.DailyReports.FirstOrDefaultAsync(r => r.IdWell == idWell && r.StartDate == startDate, token);
|
|
|
|
if (entity is null)
|
|
throw new ArgumentInvalidException("Daily report doesn`t exist", nameof(startDate));
|
|
|
|
dto.LastUpdateDate = DateTimeOffset.Now;
|
|
if (dto is HeadDto headDto)
|
|
entity.Info.Head = headDto.Adapt<Head>();
|
|
if (dto is BhaDto bhaDto)
|
|
entity.Info.Bha = bhaDto.Adapt<Bha>();
|
|
if (dto is NoDrillingDto noDrillingDto)
|
|
entity.Info.NoDrilling = noDrillingDto.Adapt<NoDrilling>();
|
|
if (dto is SaubDto saubDto)
|
|
entity.Info.Saub = saubDto.Adapt<Saub>();
|
|
if (dto is SignDto signDto)
|
|
entity.Info.Sign = signDto.Adapt<Sign>();
|
|
|
|
db.DailyReports.Update(entity);
|
|
var result = await db.SaveChangesAsync(token);
|
|
return result;
|
|
}
|
|
|
|
public async Task<Stream?> MakeReportAsync(int idWell, DateOnly date, CancellationToken token)
|
|
{
|
|
var stageIds = WellOperationCategory.WorkStages.Select(w => w.Id).ToArray();
|
|
var wellOperationCategories = wellOperationRepository.GetCategories(true)
|
|
.Where(o => o.IdParent is not null)
|
|
.Where(o => stageIds.Contains(o.IdParent!.Value));
|
|
|
|
var dailyReportDto = await GetOrDefaultAsync(idWell, date, token);
|
|
if (dailyReportDto is null)
|
|
return null;
|
|
|
|
var memoryStream = dailyReportMaker.MakeReportFromBlocks(dailyReportDto, wellOperationCategories);
|
|
|
|
return memoryStream;
|
|
}
|
|
|
|
private async Task<DailyReportDto?> GetOrDefaultAsync(int idWell, DateOnly date, CancellationToken token)
|
|
{
|
|
var entity = await db.DailyReports
|
|
.FirstOrDefaultAsync(r => r.IdWell == idWell && r.StartDate == date, token);
|
|
|
|
if (entity is null)
|
|
throw new ArgumentInvalidException("Daily report doesn`t exist", nameof(date));
|
|
|
|
var factOperationsForDtos = await GetFactOperationsForDailyReportAsync(idWell, token);
|
|
var userDtos = await userRepository.GetAllAsync(token);
|
|
var dto = Convert(entity, factOperationsForDtos, userDtos);
|
|
return dto;
|
|
}
|
|
|
|
/// <summary>
|
|
/// конвертация данных из модели базы данных в dto
|
|
/// </summary>
|
|
/// <param name="entity">модель базы данных</param>
|
|
/// <param name="factOperationsForDtos">список фактичских операций для формирования суточного рапорта</param>
|
|
/// <param name="users">список пользователей для нахождения последнего изменившего запись</param>
|
|
/// <returns></returns>
|
|
private DailyReportDto Convert(
|
|
AsbCloudDb.Model.DailyReport.DailyReport entity,
|
|
IEnumerable<WellOperationDto> factOperationsForDtos,
|
|
IEnumerable<UserExtendedDto> users)
|
|
{
|
|
var dto = entity.Info.Adapt<DailyReportDto>();
|
|
dto.StartDate = entity.StartDate;
|
|
|
|
var dailyFactOperations = factOperationsForDtos
|
|
.Where(o => DateOnly.FromDateTime(o.DateStart) == dto.StartDate)
|
|
.Where(o => o.IdParentCategory is not null);
|
|
|
|
var lastDailyFactOperation = dailyFactOperations
|
|
.OrderByDescending(o => o.LastUpdateDate)
|
|
.FirstOrDefault();
|
|
dto.TimeBalance.IdUser = lastDailyFactOperation?.IdUser;
|
|
dto.TimeBalance.LastUpdateDate = lastDailyFactOperation?.LastUpdateDate;
|
|
dto.TimeBalance.OperationsStat = dailyFactOperations
|
|
.GroupBy(o => o.IdParentCategory!.Value)
|
|
.ToDictionary(g => g.Key, g => g.Sum(o => o.DurationHours));
|
|
|
|
var blocks = new ItemInfoDto[] {
|
|
dto.Head,
|
|
dto.Bha,
|
|
dto.NoDrilling,
|
|
dto.TimeBalance,
|
|
dto.Saub,
|
|
dto.Sign
|
|
};
|
|
|
|
foreach (var block in blocks)
|
|
{
|
|
if (block.IdUser is not null)
|
|
{
|
|
block.UserName = users.FirstOrDefault(u => u.Id == block.IdUser.Value)?.MakeDisplayName()
|
|
?? $"userId:{block.IdUser.Value}";
|
|
}
|
|
}
|
|
|
|
return dto;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Создание блока "Заголовок" по умолчанию
|
|
/// </summary>
|
|
/// <param name="well"></param>
|
|
/// <param name="startDate"></param>
|
|
/// <param name="idUser"></param>
|
|
/// <returns></returns>
|
|
private Head CreateHeadDailyReportBlock(WellDto well, DateOnly startDate, int idUser)
|
|
{
|
|
var customer = well.Companies.FirstOrDefault(company => company.IdCompanyType == 1);
|
|
var contractor = well.Companies.FirstOrDefault(company => company.IdCompanyType == 2);
|
|
|
|
return new Head()
|
|
{
|
|
ReportDate = startDate,
|
|
WellName = well.Caption,
|
|
ClusterName = well?.Cluster ?? string.Empty,
|
|
Customer = customer?.Caption ?? string.Empty,
|
|
Contractor = contractor?.Caption ?? string.Empty,
|
|
IdUser = idUser,
|
|
LastUpdateDate = DateTimeOffset.Now,
|
|
};
|
|
}
|
|
}
|
|
#nullable disable
|
|
}
|