Добавить таблицу для учета комментариев и действий пользователя для вывода статистики по ChangeLog #30

Open
on.nemtina wants to merge 24 commits from feature/#956-change-log-table-comment into master
12 changed files with 73 additions and 62 deletions
Showing only changes of commit da54d24745 - Show all commits

View File

@ -10,13 +10,12 @@ using DD.Persistence.API.Services;
namespace DD.Persistence.API.Controllers; namespace DD.Persistence.API.Controllers;
[ApiController] [ApiController]
//[Authorize] [Authorize]
[Route("api/[controller]")] [Route("api/[controller]")]
public class ChangeLogController : ControllerBase, IChangeLogApi public class ChangeLogController : ControllerBase, IChangeLogApi
{ {

Не ошибка, но почему не private readonly поле как везде? +Свойства == синтаксический сахар для методов Get_..() Set_..(), А значит они должны называться с большой буквы.

Не ошибка, но почему не private readonly поле как везде? +Свойства == синтаксический сахар для методов Get_..() Set_..(), А значит они должны называться с большой буквы.
private readonly IChangeLogRepository repository; private readonly IChangeLogRepository repository;
private ChangeLogService service { get; }
public ChangeLogService service { get; }
/// <summary> /// <summary>
/// ctor /// ctor
@ -37,8 +36,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi
string comment, string comment,
CancellationToken token) CancellationToken token)
{ {
//var userId = User.GetUserId<Guid>(); var userId = User.GetUserId<Guid>();
var userId = Guid.NewGuid();
var changeLogCommit = new ChangeLogCommitDto(userId, comment, [dto]); var changeLogCommit = new ChangeLogCommitDto(userId, comment, [dto]);
var result = await service.AddRange(idDiscriminator, changeLogCommit, token); var result = await service.AddRange(idDiscriminator, changeLogCommit, token);
@ -53,8 +51,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi
string comment, string comment,
CancellationToken token) CancellationToken token)
{ {
//var userId = User.GetUserId<Guid>(); var userId = User.GetUserId<Guid>();
var userId = Guid.NewGuid();
var changeLogCommit = new ChangeLogCommitDto(userId, comment, dtos); var changeLogCommit = new ChangeLogCommitDto(userId, comment, dtos);

Скорее всего в ChangeLogCommitDto dtos - лишнее, и помешаются в методе delete например.
Отношение строчек с данными к коммиту делается уже внутри сервиса.

Скорее всего в ChangeLogCommitDto dtos - лишнее, и помешаются в методе delete например. Отношение строчек с данными к коммиту делается уже внутри сервиса.
var result = await service.AddRange(idDiscriminator, changeLogCommit, token); var result = await service.AddRange(idDiscriminator, changeLogCommit, token);
@ -66,12 +63,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi
public async Task<IActionResult> Delete(Guid id, string comment, CancellationToken token) public async Task<IActionResult> Delete(Guid id, string comment, CancellationToken token)
{ {
var userId = User.GetUserId<Guid>(); var userId = User.GetUserId<Guid>();
var changeLogCommit = new ChangeLogCommitDto() var changeLogCommit = new ChangeLogCommitDto(userId, comment, Enumerable.Empty<ChangeLogValuesDto>());
{
Comment = comment,
IdAuthor = userId,
Creation = DateTimeOffset.UtcNow,
};
var result = await service.MarkAsDeleted([id], changeLogCommit, token); var result = await service.MarkAsDeleted([id], changeLogCommit, token);
return Ok(result); return Ok(result);
@ -82,12 +74,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi
public async Task<IActionResult> DeleteRange(IEnumerable<Guid> ids, string comment, CancellationToken token) public async Task<IActionResult> DeleteRange(IEnumerable<Guid> ids, string comment, CancellationToken token)
{ {
var userId = User.GetUserId<Guid>(); var userId = User.GetUserId<Guid>();
var changeLogCommit = new ChangeLogCommitDto() var changeLogCommit = new ChangeLogCommitDto(userId, comment, Enumerable.Empty<ChangeLogValuesDto>());
{
Comment = comment,
IdAuthor = userId,
Creation = DateTimeOffset.UtcNow,
};
var result = await service.MarkAsDeleted(ids, changeLogCommit, token); var result = await service.MarkAsDeleted(ids, changeLogCommit, token);
return Ok(result); return Ok(result);
@ -101,8 +88,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi
string comment, string comment,
CancellationToken token) CancellationToken token)
{ {
//var userId = User.GetUserId<Guid>(); var userId = User.GetUserId<Guid>();
var userId = Guid.NewGuid();
var changeLogCommit = new ChangeLogCommitDto(userId, comment, dtos); var changeLogCommit = new ChangeLogCommitDto(userId, comment, dtos);
var result = await service.ClearAndAddRange(idDiscriminator, changeLogCommit, token); var result = await service.ClearAndAddRange(idDiscriminator, changeLogCommit, token);
return Ok(result); return Ok(result);
@ -115,8 +101,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi
string comment, string comment,
CancellationToken token) CancellationToken token)
{ {
//var userId = User.GetUserId<Guid>(); var userId = User.GetUserId<Guid>();
var userId = Guid.NewGuid();
var changeLogCommit = new ChangeLogCommitDto(userId, comment, [dto]); var changeLogCommit = new ChangeLogCommitDto(userId, comment, [dto]);
var result = await service.UpdateRange(changeLogCommit, token); var result = await service.UpdateRange(changeLogCommit, token);
@ -130,8 +115,7 @@ public class ChangeLogController : ControllerBase, IChangeLogApi
string comment, string comment,
CancellationToken token) CancellationToken token)
{ {
//var userId = User.GetUserId<Guid>(); var userId = User.GetUserId<Guid>();
var userId = Guid.NewGuid();
var changeLogCommit = new ChangeLogCommitDto(userId, comment, dtos); var changeLogCommit = new ChangeLogCommitDto(userId, comment, dtos);
var result = await service.UpdateRange(changeLogCommit, token); var result = await service.UpdateRange(changeLogCommit, token);

View File

@ -1,11 +1,12 @@
using DD.Persistence.Database.Entity; using DD.Persistence.Models.Requests;
using DD.Persistence.Models.Requests;
using DD.Persistence.Repositories; using DD.Persistence.Repositories;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Caching.Memory;
using Newtonsoft.Json.Linq;
namespace DD.Persistence.API.Services; namespace DD.Persistence.API.Services;
/// <summary>
/// Сервис по работе с журналом изменений
/// </summary>
public class ChangeLogService public class ChangeLogService
{ {
private readonly IMemoryCache memoryCache; private readonly IMemoryCache memoryCache;
@ -13,6 +14,12 @@ public class ChangeLogService
private readonly IChangeLogRepository repository; private readonly IChangeLogRepository repository;
private readonly TimeSpan? AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(60); private readonly TimeSpan? AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(60);
/// <summary>
/// ctor
/// </summary>
/// <param name="memoryCache"></param>
/// <param name="commitRepository"></param>
/// <param name="repository"></param>
public ChangeLogService( public ChangeLogService(
IMemoryCache memoryCache, IMemoryCache memoryCache,
IChangeLogCommitRepository commitRepository, IChangeLogCommitRepository commitRepository,
@ -23,7 +30,13 @@ public class ChangeLogService
this.repository = repository; this.repository = repository;
} }
private async Task<Guid> GetOrCreateAsync(ChangeLogCommitDto commitDto, CancellationToken token) /// <summary>
/// Создание или чтение данных коммита
/// </summary>
/// <param name="commitDto"></param>
/// <param name="token"></param>

Тут мы не читаем данные коммита. Только получаем его Id.
Не правильное название и описание.

Тут мы не читаем данные коммита. Только получаем его Id. Не правильное название и описание.
/// <returns></returns>
private async Task<Guid> GetOrCreateCommitAsync(ChangeLogCommitDto commitDto, CancellationToken token)
{ {
var key = (commitDto.IdAuthor, commitDto.Comment); var key = (commitDto.IdAuthor, commitDto.Comment);
var commitId = await memoryCache.GetOrCreateAsync(key, async (cacheEntry) => var commitId = await memoryCache.GetOrCreateAsync(key, async (cacheEntry) =>
Review

Давай в кеше хранить комит целиком не только ID

Давай в кеше хранить комит целиком не только ID
@ -37,18 +50,32 @@ public class ChangeLogService
return commitId; return commitId;
} }
/// <summary>
/// Добавление записи в журнал изменений
/// </summary>
/// <param name="idDiscriminator"></param>
/// <param name="commitDto"></param>
/// <param name="token"></param>
/// <returns></returns>
public async Task<int> AddRange(Guid idDiscriminator, ChangeLogCommitDto commitDto, CancellationToken token) public async Task<int> AddRange(Guid idDiscriminator, ChangeLogCommitDto commitDto, CancellationToken token)
{ {
var commitId = await GetOrCreateAsync(commitDto, token); var commitId = await GetOrCreateCommitAsync(commitDto, token);
commitDto.Id = commitId; commitDto.Id = commitId;
var result = await repository.AddRange(idDiscriminator, commitDto, token); var result = await repository.AddRange(idDiscriminator, commitDto, token);
return result; return result;
} }
/// <summary>
/// Пометить запись журнала изменений как удаленную
/// </summary>
/// <param name="ids"></param>
/// <param name="commitDto"></param>
/// <param name="token"></param>
/// <returns></returns>
public async Task<int> MarkAsDeleted(IEnumerable<Guid> ids, ChangeLogCommitDto commitDto, CancellationToken token) public async Task<int> MarkAsDeleted(IEnumerable<Guid> ids, ChangeLogCommitDto commitDto, CancellationToken token)
{ {
var commitId = await GetOrCreateAsync(commitDto, token); var commitId = await GetOrCreateCommitAsync(commitDto, token);
commitDto.Id = commitId; commitDto.Id = commitId;
var result = await repository.MarkAsDeleted(commitId, ids, commitDto.Creation, token); var result = await repository.MarkAsDeleted(commitId, ids, commitDto.Creation, token);
@ -56,9 +83,16 @@ public class ChangeLogService
return result; return result;
} }
/// <summary>
/// Очистить старые и добавить новые записи в журнал изменений
/// </summary>
/// <param name="idDiscriminator"></param>
/// <param name="commitDto"></param>
/// <param name="token"></param>
/// <returns></returns>
public async Task<int> ClearAndAddRange(Guid idDiscriminator, ChangeLogCommitDto commitDto, CancellationToken token) public async Task<int> ClearAndAddRange(Guid idDiscriminator, ChangeLogCommitDto commitDto, CancellationToken token)
{ {
var commitId = await GetOrCreateAsync(commitDto, token); var commitId = await GetOrCreateCommitAsync(commitDto, token);
commitDto.Id = commitId; commitDto.Id = commitId;
var result = await repository.ClearAndAddRange(idDiscriminator, commitDto, token); var result = await repository.ClearAndAddRange(idDiscriminator, commitDto, token);
@ -66,9 +100,15 @@ public class ChangeLogService
return result; return result;
} }
/// <summary>
/// Обновить записи в журнале изменений
/// </summary>
/// <param name="changeLogCommit"></param>
/// <param name="token"></param>
/// <returns></returns>
public async Task<int> UpdateRange(ChangeLogCommitDto changeLogCommit, CancellationToken token) public async Task<int> UpdateRange(ChangeLogCommitDto changeLogCommit, CancellationToken token)
{ {
var commitId = await GetOrCreateAsync(changeLogCommit, token); var commitId = await GetOrCreateCommitAsync(changeLogCommit, token);
changeLogCommit.Id = commitId; changeLogCommit.Id = commitId;
var result = await repository.UpdateRange(changeLogCommit, token); var result = await repository.UpdateRange(changeLogCommit, token);

View File

@ -1,7 +1,7 @@
{ {
"DbConnection": { "DbConnection": {
"Host": "localhost", "Host": "postgres",
"Port": 5462, "Port": 5432,
"Database": "persistence", "Database": "persistence",
"Username": "postgres", "Username": "postgres",
"Password": "postgres" "Password": "postgres"

View File

@ -17,7 +17,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\DD.Persistence.API\DD.Persistence.API.csproj" />
<ProjectReference Include="..\DD.Persistence.Database.Postgres\DD.Persistence.Database.Postgres.csproj" /> <ProjectReference Include="..\DD.Persistence.Database.Postgres\DD.Persistence.Database.Postgres.csproj" />
</ItemGroup> </ItemGroup>

View File

@ -13,8 +13,8 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace DD.Persistence.Database.Postgres.Migrations namespace DD.Persistence.Database.Postgres.Migrations
{ {
[DbContext(typeof(PersistencePostgresContext))] [DbContext(typeof(PersistencePostgresContext))]
[Migration("20250214113032_Initial")] [Migration("20250218052129_Init")]
partial class Initial partial class Init
{ {
/// <inheritdoc /> /// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder) protected override void BuildTargetModel(ModelBuilder modelBuilder)

View File

@ -7,7 +7,7 @@ using Microsoft.EntityFrameworkCore.Migrations;
namespace DD.Persistence.Database.Postgres.Migrations namespace DD.Persistence.Database.Postgres.Migrations
{ {
/// <inheritdoc /> /// <inheritdoc />
public partial class Initial : Migration public partial class Init : Migration
{ {
/// <inheritdoc /> /// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder) protected override void Up(MigrationBuilder migrationBuilder)

View File

@ -16,7 +16,7 @@ public class PersistenceDbContext : DbContext
public DbSet<ChangeLog> ChangeLog => Set<ChangeLog>(); public DbSet<ChangeLog> ChangeLog => Set<ChangeLog>();
public DbSet<ChangeLogCommit> ChangeLogAction => Set<ChangeLogCommit>(); public DbSet<ChangeLogCommit> ChangeLogCommit => Set<ChangeLogCommit>();
public DbSet<TechMessage> TechMessage => Set<TechMessage>(); public DbSet<TechMessage> TechMessage => Set<TechMessage>();

View File

@ -15,10 +15,6 @@ public class ChangeLogCommitRepository : IChangeLogCommitRepository
{ {
private DbContext db; private DbContext db;
public ChangeLogCommitRepository()
{
}
public ChangeLogCommitRepository(DbContext db) public ChangeLogCommitRepository(DbContext db)
{ {
this.db = db; this.db = db;

View File

@ -40,11 +40,11 @@ public class ChangeLogControllerTest : BaseIntegrationTest
{ {
// arrange // arrange
var insertedCount = 10; var insertedCount = 10;
var newEntitiesData = await CreateAndReturnNewDtos(insertedCount, (-15, 15)); var newEntitiesData = await CreateAndReturnNewDtos(insertedCount, (-15, -1));
var idDiscriminator = newEntitiesData.Item1; var idDiscriminator = newEntitiesData.Item1;
var dtos = newEntitiesData.Item2; var dtos = newEntitiesData.Item2;
//act
var result = await client.ClearAndAddRange(idDiscriminator, dtos, "Добавление новых элементов и очистка старых", CancellationToken.None); var result = await client.ClearAndAddRange(idDiscriminator, dtos, "Добавление новых элементов и очистка старых", CancellationToken.None);
// assert // assert
@ -218,7 +218,7 @@ public class ChangeLogControllerTest : BaseIntegrationTest
//создаем записи //создаем записи
var count = 5; var count = 5;
var changeLogItems = await CreateAndReturnNewDtos(count, (-15, 15)); var changeLogItems = await CreateAndReturnNewDtos(count, (-15, -1));
var idDiscriminator = changeLogItems.Item1; var idDiscriminator = changeLogItems.Item1;
var entities = changeLogItems.Item2; var entities = changeLogItems.Item2;
@ -322,7 +322,7 @@ public class ChangeLogControllerTest : BaseIntegrationTest
Creation = DateTimeOffset.UtcNow, Creation = DateTimeOffset.UtcNow,
Id = Guid.NewGuid(), Id = Guid.NewGuid(),
}; };
dbContext.ChangeLogAction.Add(commit); dbContext.ChangeLogCommit.Add(commit);
await dbContext.SaveChangesAsync(); await dbContext.SaveChangesAsync();
var minDayCount = daysRange.Item1; var minDayCount = daysRange.Item1;

View File

@ -30,14 +30,6 @@ public class ChangeLogCommitDto
/// </summary> /// </summary>
public IEnumerable<ChangeLogValuesDto> ChangeLogItems { get; set; } public IEnumerable<ChangeLogValuesDto> ChangeLogItems { get; set; }
/// <summary>
/// ctor
/// </summary>
public ChangeLogCommitDto()
{
}
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>

View File

@ -19,7 +19,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\DD.Persistence.API\DD.Persistence.API.csproj" /> <ProjectReference Include="..\DD.Persistence.Database.Postgres\DD.Persistence.Database.Postgres.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -8,12 +8,12 @@ using System.Threading.Tasks;
namespace DD.Persistence.Repositories; namespace DD.Persistence.Repositories;
/// <summary> /// <summary>
/// /// Интерфейс для работы с коммитами журнала изменений
/// </summary> /// </summary>
public interface IChangeLogCommitRepository public interface IChangeLogCommitRepository
{ {
/// <summary> /// <summary>
/// /// Добавить коммит для журнала изменений
/// </summary> /// </summary>
/// <param name="commitDto"></param> /// <param name="commitDto"></param>
/// <param name="token"></param> /// <param name="token"></param>