persistence/DD.Persistence.API/Services/ChangeLogService.cs

272 lines
10 KiB
C#
Raw Normal View History

using DD.Persistence.Models;
using DD.Persistence.Models.Common;
2025-02-18 15:43:27 +05:00
using DD.Persistence.Models.Requests;
using DD.Persistence.Models.Requests.ChangeLog;
using DD.Persistence.Repositories;
2025-02-13 17:57:43 +05:00
using Microsoft.Extensions.Caching.Memory;
namespace DD.Persistence.API.Services;
/// <summary>
/// Сервис по работе с журналом изменений
/// </summary>
public class ChangeLogService
2025-02-13 17:57:43 +05:00
{
private readonly IMemoryCache memoryCache;
private readonly IChangeLogCommitRepository commitRepository;
private readonly IChangeLogRepository repository;
private readonly TimeSpan? AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(60);
/// <summary>
/// ctor
/// </summary>
/// <param name="memoryCache"></param>
/// <param name="commitRepository"></param>
/// <param name="repository"></param>
2025-02-13 17:57:43 +05:00
public ChangeLogService(
IMemoryCache memoryCache,
IChangeLogCommitRepository commitRepository,
IChangeLogRepository repository)
{
this.memoryCache = memoryCache;
this.commitRepository = commitRepository;
this.repository = repository;
}
/// <summary>
/// Чтение или создание нового коммита
/// </summary>
/// <param name="request"></param>
/// <param name="token"></param>
/// <returns></returns>
private async Task<ChangeLogCommitDto> GetOrCreateCommitAsync(CreateChangeLogCommitRequest request, CancellationToken token)
2025-02-13 17:57:43 +05:00
{
var key = (request.IdAuthor, request.Comment);
var commit = await memoryCache.GetOrCreateAsync(key, async (cacheEntry) =>
2025-02-13 17:57:43 +05:00
{
cacheEntry.AbsoluteExpirationRelativeToNow = AbsoluteExpirationRelativeToNow;
var commit = await commitRepository.Add(request, token);
2025-02-13 17:57:43 +05:00
return commit;
2025-02-13 17:57:43 +05:00
});
return commit!;
2025-02-13 17:57:43 +05:00
}
/// <summary>
/// Добавление записи в журнал изменений
/// </summary>
/// <param name="idDiscriminator"></param>
/// <param name="request"></param>
/// <param name="dtos"></param>
/// <param name="token"></param>
/// <returns></returns>
public async Task<int> AddRange(Guid idDiscriminator, CreateChangeLogCommitRequest request, IEnumerable<ChangeLogValuesDto> dtos, CancellationToken token)
{
var commit = await GetOrCreateCommitAsync(request, token);
var result = await repository.AddRange(idDiscriminator, commit, dtos, token);
return result;
}
/// <summary>
/// Пометить запись журнала изменений как удаленную
/// </summary>
/// <param name="ids"></param>
/// <param name="request"></param>
/// <param name="token"></param>
/// <returns></returns>
public async Task<int> MarkAsDeleted(IEnumerable<Guid> ids, CreateChangeLogCommitRequest request, CancellationToken token)
2025-02-13 17:57:43 +05:00
{
var commit = await GetOrCreateCommitAsync(request, token);
var result = await repository.MarkAsDeleted(ids, commit, token);
return result;
}
/// <summary>
/// Очистить старые и добавить новые записи в журнал изменений
/// </summary>
/// <param name="idDiscriminator"></param>
/// <param name="request"></param>
/// <param name="dtos"></param>
/// <param name="token"></param>
/// <returns></returns>
public async Task<int> ClearAndAddRange(Guid idDiscriminator, CreateChangeLogCommitRequest request, IEnumerable<ChangeLogValuesDto> dtos, CancellationToken token)
{
var commit = await GetOrCreateCommitAsync(request, token);
var result = await repository.ClearAndAddRange(idDiscriminator, commit, dtos, token);
return result;
}
/// <summary>
/// Обновить записи в журнале изменений
/// </summary>
/// <param name="commitRequest"></param>
/// <param name="dtos"></param>
/// <param name="token"></param>
/// <returns></returns>
public async Task<int> UpdateRange(CreateChangeLogCommitRequest commitRequest, IEnumerable<ChangeLogValuesDto> dtos, CancellationToken token)
{
var commit = await GetOrCreateCommitAsync(commitRequest, token);
var result = await repository.UpdateRange(commit, dtos, token);
return result;
2025-02-13 17:57:43 +05:00
}
2025-02-18 15:43:27 +05:00
/// <summary>
/// Получение актуальных записей на определенный момент времени (с пагинацией)
/// </summary>
/// <param name="idDiscriminator"></param>
/// <param name="momentUtc"></param>
/// <param name="paginationRequest"></param>
/// <param name="token"></param>
/// <returns></returns>
public async Task<PaginationContainer<ChangeLogValuesDto>> GetByDate(
Guid idDiscriminator,
DateTimeOffset momentUtc,
PaginationRequest paginationRequest,
CancellationToken token)
{
var result = await repository.GetByDate(idDiscriminator, momentUtc, paginationRequest, token);
return result;
}
/// <summary>
/// Получение измененных записей за период времени
/// </summary>
/// <param name="idDiscriminator"></param>
/// <param name="dateBegin"></param>
/// <param name="dateEnd"></param>
/// <param name="token"></param>
/// <returns></returns>
public async Task<IEnumerable<ChangeLogDto>> GetChangeLogForInterval(Guid idDiscriminator, DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token)
{
var result = await repository.GetChangeLogForInterval(idDiscriminator, dateBegin, dateEnd, token);
return result;
}
/// <summary>
/// Получение списка дат, в которые происходили изменения (день, месяц, год, без времени)
/// </summary>
/// <param name="idDiscriminator"></param>
/// <param name="token"></param>
/// <returns></returns>
public async Task<IEnumerable<DateOnly>> GetDatesChange(Guid idDiscriminator, CancellationToken token)
{
var result = await repository.GetDatesChange(idDiscriminator, token);
return result;
}
/// <summary>
/// Получить данные, начиная с определенной даты
/// </summary>
/// <param name="idDiscriminator"></param>
/// <param name="dateBegin"></param>
/// <param name="token"></param>
/// <returns></returns>
public async Task<IEnumerable<ChangeLogValuesDto>> GetGtDate(Guid idDiscriminator, DateTimeOffset dateBegin, CancellationToken token)
{
var result = await repository.GetGtDate(idDiscriminator, dateBegin, token);
return result;
2025-02-18 15:43:27 +05:00
}
/// <summary>
/// Получить диапазон дат, для которых есть данные в репозитории
/// </summary>
/// <param name="idDiscriminator"></param>
/// <param name="token"></param>
/// <returns></returns>
public async Task<DatesRangeDto?> GetDatesRange(Guid idDiscriminator, CancellationToken token)
{
var result = await repository.GetDatesRange(idDiscriminator, token);
return result;
}
/// <summary>
/// Метод получения статистики пользователя по количеству изменений в разрезе дней
/// </summary>
/// <param name="request"></param>
/// <param name="token"></param>
/// <returns></returns>
public async Task<IEnumerable<StatisticsChangeLogDto>> GetUserStatisticsCount(ChangeLogRequest request, CancellationToken token)
{
var commitData = await commitRepository.GetCreatedAndObsoleted(request.DiscriminatorId, request.UserId, token);
var commitCreated = commitData.Item1.OrderBy(c => c.Creation);
var commitObsoleted = commitData.Item2.OrderBy(c => c.Creation);
if (!commitCreated.Any())
return Enumerable.Empty<StatisticsChangeLogDto>();
var minDateTime = commitCreated.FirstOrDefault()!.Creation;
var minDate = new DateOnly(minDateTime.Year, minDateTime.Month, minDateTime.Day);
var lastCommitCreated = commitCreated.Last();
var lastCommitObsoleted = commitObsoleted.LastOrDefault();
var maxDateTime = lastCommitCreated.Creation;
if ((lastCommitObsoleted != null) && (lastCommitObsoleted.Creation > maxDateTime))
maxDateTime = lastCommitObsoleted.Creation;
var maxDate = new DateOnly(maxDateTime.Year, maxDateTime.Month, maxDateTime.Day);
var result = new List<StatisticsChangeLogDto>();
while (minDate <= maxDate)
{
var createdCount = commitCreated
.Where(c => new DateOnly(c.Creation.Year, c.Creation.Month, c.Creation.Day) == minDate)
.Count();
var obsoletedCount = commitObsoleted
.Where(c => new DateOnly(c.Creation.Year, c.Creation.Month, c.Creation.Day) == minDate)
.Count();
result.Add(new StatisticsChangeLogDto()
{
Date = minDate,
CreatedCount = createdCount,
ObsoletedCount = obsoletedCount,
Count = createdCount + obsoletedCount
});
}
return result;
}
/// <summary>
///
/// </summary>
/// <param name="request"></param>
/// <param name="token"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public async Task<IEnumerable<HistoryChangeLogDto>> GetHistoryChangeLog(ChangeLogRequest request, CancellationToken token)
{
var commits = await commitRepository.Get(request.DiscriminatorId, request.UserId, token);
if (!commits.Any())
return Enumerable.Empty<HistoryChangeLogDto>();
var result = commits.Select(c => new HistoryChangeLogDto()
{
ChangeLogItems = new List<ChangeLogDto>(),
Comment = c.Comment ?? string.Empty,
DateTime = c.Creation,
User = new UserDto() {
DisplayName = "",
Id = c.IdAuthor,
}
});
return result;
}
2025-02-13 17:57:43 +05:00
}