DD.WellWorkover.Cloud/AsbCloudInfrastructure/Repository/ProcessMapPlanBaseRepository.cs
2024-01-20 15:38:37 +05:00

271 lines
9.1 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.ProcessMapPlan;
using AsbCloudApp.Exceptions;
using AsbCloudApp.Repositories;
using AsbCloudApp.Requests;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using AsbCloudDb.Model.ProcessMapPlan;
using Mapster;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Repository;
public class ProcessMapPlanBaseRepository<TDto, TEntity> : IProcessMapPlanBaseRepository<TDto>
where TDto : ProcessMapPlanBaseDto
where TEntity : ProcessMapPlanBase
{
private readonly IAsbCloudDbContext context;
private readonly IWellService wellService;
public ProcessMapPlanBaseRepository(IAsbCloudDbContext context, IWellService wellService)
{
this.context = context;
this.wellService = wellService;
}
public async Task<int> InsertRange(int idUser, IEnumerable<TDto> dtos, CancellationToken token)
{
var result = 0;
if (dtos.Any())
{
var entities = dtos.Select(Convert);
var creation = DateTimeOffset.UtcNow;
var dbSet = context.Set<TEntity>();
foreach (var entity in entities) {
entity.Id = default;
entity.IdAuthor = idUser;
entity.Creation = creation;
entity.IdState = ChangeLogAbstract.IdStateActual;
entity.IdEditor = null;
entity.Editor = null;
entity.IdPrevious = null;
entity.Obsolete = null;
dbSet.Add(entity);
}
result += await context.SaveChangesAsync(token);
}
return result;
}
public async Task<int> ClearAndInsertRange(int idUser, int idWell, IEnumerable<TDto> dtos, CancellationToken token)
{
if (dtos.Any(d => d.IdWell != idWell))
throw new ArgumentInvalidException(nameof(dtos), $"Все записи должны относиться к скважине idWell = {idWell}");
using var transaction = context.Database.BeginTransaction();
var result = 0;
try
{
var dbSet = context.Set<TEntity>();
var entitiesToMarkDeleted = dbSet
.Where(e => e.IdWell == idWell)
.Where(e => e.Obsolete == null);
var obsolete = DateTimeOffset.UtcNow;
foreach (var entity in entitiesToMarkDeleted)
{
entity.IdState = ChangeLogAbstract.IdClearedOnImport;
entity.Obsolete = obsolete;
entity.IdEditor = idUser;
}
result += await context.SaveChangesAsync(token);
result += await InsertRange(idUser, dtos, token);
await transaction.CommitAsync(token);
}
catch
{
await transaction.RollbackAsync(CancellationToken.None);
throw;
}
return result;
}
public async Task<int> DeleteRange(int idUser, IEnumerable<int> ids, CancellationToken token)
{
var dbSet = context.Set<TEntity>();
var entitiesToMarkDeleted = dbSet
.Where(e => ids.Contains(e.Id))
.Where(e => e.Obsolete == null);
var obsolete = DateTimeOffset.UtcNow;
foreach (var entity in entitiesToMarkDeleted)
{
entity.IdState = ChangeLogAbstract.IdStateDeleted;
entity.Obsolete = obsolete;
entity.IdEditor = idUser;
}
var result = await context.SaveChangesAsync(token);
return result;
}
public async Task<IEnumerable<TDto>> Get(ProcessMapPlanBaseRequest request, CancellationToken token)
{
var timezone = wellService.GetTimezone(request.IdWell);
var offset = TimeSpan.FromHours(timezone.Hours);
var query = context
.Set<TEntity>()
.Where(e => e.IdWell == request.IdWell);
if(request.IdWellSectionType.HasValue)
query = query.Where(e => e.IdWellSectionType == request.IdWellSectionType);
if (request.UpdateFrom.HasValue)
{
var from = request.UpdateFrom.Value.ToUniversalTime();
query = query.Where(e => e.Creation >= from || e.Obsolete >= from);
}
if (request.Moment.HasValue)
{
var moment = request.Moment.Value.ToUniversalTime();
query = query
.Where(e => e.Creation < moment)
.Where(e => e.Obsolete == null || e.Obsolete > moment);
}
var entities = await query.ToArrayAsync(token);
var dtos = entities.Select(e => Convert(e, offset));
return dtos;
}
public async Task<IEnumerable<TDto>> GetChangeLog(int idWell, DateOnly? date, CancellationToken token)
{
var query = context
.Set<TEntity>()
.Where(e => e.IdWell == idWell);
var timezone = wellService.GetTimezone(idWell);
var offset = TimeSpan.FromHours(timezone.Hours);
if (date.HasValue)
{
var min = new DateTimeOffset(date.Value.Year, date.Value.Month, date.Value.Day, 0, 0, 0, offset).ToUniversalTime();
var max = min.AddDays(1);
var createdQuery = query.Where(e => e.Creation >= min && e.Creation <= max);
var editedQuery = query.Where(e => e.Obsolete != null && e.Obsolete >= min && e.Obsolete <= max);
query = createdQuery.Union(editedQuery);
}
var entities = await query.ToListAsync(token);
var dtos = entities.Select(e => Convert(e, offset));
return dtos;
}
public async Task<IEnumerable<DateOnly>> GetDatesChange(int idWell, CancellationToken token)
{
var wellEntitiesQuery = context
.Set<TEntity>()
.Where(e => e.IdWell == idWell);
var datesCreateQuery = wellEntitiesQuery
.Select(e => e.Creation)
.Distinct();
var datesCreate = await datesCreateQuery.ToArrayAsync(token);
var datesUpdateQuery = wellEntitiesQuery
.Where(e => e.Obsolete != null)
.Select(e => e.Obsolete!.Value)
.Distinct();
var datesUpdate = await datesUpdateQuery.ToArrayAsync(token);
var timezone = wellService.GetTimezone(idWell);
var offset = TimeSpan.FromHours(timezone.Hours);
var dates = Enumerable.Concat( datesCreate, datesUpdate);
dates = dates.Select(date => date.ToOffset(offset));
var datesOnly = dates
.Select(d => new DateOnly(d.Year, d.Month, d.Day))
.Distinct();
return datesOnly;
}
public async Task<int> UpdateRange(int idUser, IEnumerable<TDto> dtos, CancellationToken token)
{
if (dtos.Any(d => d.Id == 0))
throw new ArgumentInvalidException(nameof(dtos), "Отредактированные значения должны иметь id больше 0");
if (!dtos.Any())
return 0;
using var transaction = context.Database.BeginTransaction();
var result = 0;
try
{
var ids = dtos.Select(d => d.Id);
var dbSet = context.Set<TEntity>();
var entitiesToDelete = dbSet
.Where(e => ids.Contains(e.Id));
var updateTime = DateTimeOffset.UtcNow;
foreach (var entity in entitiesToDelete)
{
if(entity.Obsolete is not null)
throw new ArgumentInvalidException(nameof(dtos), "Недопустимо редактировать устаревшие записи");
entity.IdState = ChangeLogAbstract.IdStateReplaced;
entity.Obsolete = updateTime;
entity.IdEditor = idUser;
}
result += await context.SaveChangesAsync(token);
var entitiesNew = dtos.Select(Convert);
foreach (var entity in entitiesNew)
{
entity.IdPrevious = entity.Id;
entity.Id = default;
entity.Creation = updateTime;
entity.IdAuthor = idUser;
entity.Obsolete = null;
entity.IdEditor = null;
entity.IdState = ChangeLogAbstract.IdStateActual;
dbSet.Add(entity);
}
result += await context.SaveChangesAsync(token);
await transaction.CommitAsync(token);
}
catch
{
await transaction.RollbackAsync(CancellationToken.None);
throw;
}
return result;
}
protected virtual TEntity Convert(TDto dto)
{
var entity = dto.Adapt<TEntity>();
entity.Creation = entity.Creation.ToUniversalTime();
if(entity.Obsolete.HasValue)
entity.Obsolete = entity.Obsolete.Value.ToUniversalTime();
return entity;
}
protected virtual TDto Convert(TEntity entity, TimeSpan offset)
{
var dto = entity.Adapt<TDto>();
dto.Creation = entity.Creation.ToOffset(offset);
if (entity.Obsolete.HasValue)
dto.Obsolete = entity.Obsolete.Value.ToOffset(offset);
return dto;
}
}