DD.WellWorkover.Cloud/AsbCloudInfrastructure/Services/MeasureService.cs

163 lines
6.1 KiB
C#

using AsbCloudApp.Data;
using AsbCloudApp.Exceptions;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using Mapster;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Services
{
#nullable enable
public class MeasureService : IMeasureService
{
private readonly IAsbCloudDbContext db;
private readonly IMemoryCache memoryCache;
private readonly IWellService wellService;
private static readonly TimeSpan CacheOlescence = TimeSpan.FromMinutes(20);
public MeasureService(IAsbCloudDbContext db, IMemoryCache memoryCache, IWellService wellService)
{
this.db = db;
this.memoryCache = memoryCache;
this.wellService = wellService;
}
public async Task<Dictionary<int, string>> GetCategoriesAsync(CancellationToken token)
{
var key = typeof(MeasureCategory).FullName;
var cache = await memoryCache.GetOrCreateAsync(key, async (cacheEntry) => {
cacheEntry.AbsoluteExpirationRelativeToNow = CacheOlescence;
cacheEntry.SlidingExpiration = CacheOlescence;
var entities = await db.Set<MeasureCategory>()
.ToDictionaryAsync(e => e.Id, e => e.Name, token);
return entities;
});
return cache;
}
public async Task<MeasureDto?> GetLastOrDefaultAsync(int idWell, int idCategory, CancellationToken token)
{
var query = db.Measures
.Include(m => m.Category)
.Where(m => m.IdWell == idWell && m.IdCategory == idCategory && !m.IsDeleted)
.OrderByDescending(m => m.Timestamp)
.Take(1);
var entity = await query
.AsNoTracking()
.FirstOrDefaultAsync(token)
.ConfigureAwait(false);
var timezone = wellService.GetTimezone(idWell);
if (entity is null)
return null;
return Convert(entity, timezone.Hours);
}
public async Task<IEnumerable<MeasureDto>> GetHisoryAsync(int idWell, int? idCategory = null, CancellationToken token = default)
{
var query = db.Measures.Include(m => m.Category)
.Where(m => m.IdWell == idWell && !m.IsDeleted);
if (idCategory is not null)
query = query.Where(m => m.IdCategory == idCategory);
var entities = await query
.OrderBy(m => m.Timestamp)
.AsNoTracking()
.ToListAsync(token)
.ConfigureAwait(false);
var timezone = wellService.GetTimezone(idWell);
var dtos = entities.Select(e => Convert(e, timezone.Hours));
return dtos;
}
public Task<int> InsertAsync(int idWell, MeasureDto dto, CancellationToken token)
{
if (dto.IdCategory < 1)
throw new ArgumentInvalidException("wrong idCategory", nameof(dto));
if (dto.Data is null)
throw new ArgumentInvalidException("data.data is not optional", nameof(dto));
var timezone = wellService.GetTimezone(idWell);
var entity = Convert(dto, timezone.Hours);
entity.IdWell = idWell;
db.Measures.Add(entity);
return db.SaveChangesAsync(token);
}
public async Task<int> UpdateAsync(int idWell, MeasureDto dto, CancellationToken token)
{
if (dto.Id < 1)
throw new ArgumentInvalidException("wrong id", nameof(dto));
if (dto.IdCategory < 1)
throw new ArgumentInvalidException("wrong idCategory", nameof(dto));
if (dto.Data is null)
throw new ArgumentInvalidException("data.data is not optional", nameof(dto));
var entity = await db.Measures
.Where(m => m.Id == dto.Id && !m.IsDeleted)
.FirstOrDefaultAsync(token)
.ConfigureAwait(false);
if (entity is null)
throw new ArgumentInvalidException("id doesn't exist", nameof(dto));
var timezone = wellService.GetTimezone(idWell);
entity.IdWell = idWell;
entity.Timestamp = dto.Timestamp.ToUtcDateTimeOffset(timezone.Hours);
entity.Data = dto.Data.Adapt<RawData>();
return await db.SaveChangesAsync(token).ConfigureAwait(false);
}
public async Task<int> MarkAsDeleteAsync(int idWell, int idData, CancellationToken token)
{
if (idData < 1)
throw new ArgumentInvalidException("wrong id", nameof(idData));
var entity = await db.Measures.Where(m => m.IdWell == idWell && m.Id == idData)
.FirstOrDefaultAsync(token)
.ConfigureAwait(false);
if (entity is null)
throw new ArgumentInvalidException($"Measure doesn't exist", nameof(idWell));
entity.IsDeleted = true;
return await db.SaveChangesAsync(token).ConfigureAwait(false);
}
public Task<int> DeleteAsync(int idWell, int idData, CancellationToken token)
{
if (idData < 1)
throw new ArgumentInvalidException("wrong id", nameof(idData));
db.Measures.RemoveRange(db.Measures.Where(m => m.IdWell == idWell && m.Id == idData));
return db.SaveChangesAsync(token);
}
private MeasureDto Convert(Measure entity, double hours)
{
var dto = entity.Adapt<MeasureDto>();
dto.CategoryName = entity.Category?.Name ?? String.Empty;
dto.Timestamp = entity.Timestamp.ToRemoteDateTime(hours);
return dto;
}
private Measure Convert(MeasureDto dto, double hours)
{
var entity = dto.Adapt<Measure>();
entity.Timestamp = dto.Timestamp.ToUtcDateTimeOffset(hours);
return entity;
}
}
#nullable disable
}