Skip to content

Commit b410535

Browse files
authored
Merge pull request #133 from samuelzedec/develop
refactor: unificar BaseEntity e BaseModel em Tracker para herança simplificada
2 parents a1daa1a + 940d9d3 commit b410535

File tree

21 files changed

+211
-288
lines changed

21 files changed

+211
-288
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
# Riber - Changelog
22

3+
## v4.2.1 - 07/11/2025
4+
- **REFATORAÇÃO**: Unificar BaseEntity e BaseModel em Tracker para herança simplificada
5+
- Remove `BaseEntityConfiguration` e `BaseModelConfiguration`, substituindo por `BaseTypeConfiguration`
6+
- Introduz abstração `Tracker` consolidando propriedades e métodos comuns
7+
- Atualiza modelos e mapeamentos para herdar de `Tracker`
8+
- Simplifica lógica de auditoria em `AuditInterceptor` para manipular exclusivamente entidades `Tracker`
9+
- Reorganiza mapeamentos seguindo a nova estrutura de herança
10+
11+
---
12+
313
## v4.2.0 - 04/11/2025
414
- **NOVO**: Serviço para geração de Embeddings Genérico
515
- Adiciona um evento para gerar embeddings dos produtos

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<Companies>Samuel Zedec</Companies>
55
<Copyright>Copyright © $([System.DateTime]::Now.Year)</Copyright>
66
<Description>Sistema de gestão financeira para um lanchonete local</Description>
7-
<Version>4.2.0</Version>
7+
<Version>4.2.1</Version>
88
</PropertyGroup>
99

1010
<!-- Repositório e Documentação -->
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
namespace Riber.Domain.Abstractions;
2+
3+
/// <summary>
4+
/// Define um contrato para rastreamento das propriedades fundamentais de uma entidade, incluindo seu identificador único
5+
/// e marcações temporais para criação, última atualização e exclusão lógica.
6+
/// </summary>
7+
public abstract class Tracker(Guid id)
8+
{
9+
#region Properties
10+
11+
public Guid Id { get; } = id;
12+
public DateTime CreatedAt { get; } = DateTime.UtcNow;
13+
public DateTime? UpdatedAt { get; private set; }
14+
public DateTime? DeletedAt { get; private set; }
15+
16+
#endregion
17+
18+
#region Methods
19+
20+
public void UpdateEntity()
21+
=> UpdatedAt = DateTime.UtcNow;
22+
23+
public void DeleteEntity()
24+
=> DeletedAt = DateTime.UtcNow;
25+
26+
#endregion
27+
}

src/Riber.Domain/Entities/BaseEntity.cs

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,15 @@ namespace Riber.Domain.Entities;
66
/// Representa uma entidade base abstrata que fornece funcionalidades comuns para entidades de domínio.
77
/// Esta classe inclui um identificador, gerenciamento de eventos de domínio e mecanismos de comparação de igualdade.
88
/// </summary>
9-
public abstract class BaseEntity(Guid id) : IEquatable<BaseEntity>
9+
public abstract class BaseEntity(Guid id)
10+
: Tracker(id), IEquatable<BaseEntity>
1011
{
1112
#region Private Members
1213

1314
private readonly List<IDomainEvent> _events = [];
1415

1516
#endregion
1617

17-
#region Properties
18-
19-
public Guid Id { get; } = id;
20-
public DateTime CreatedAt { get; } = DateTime.UtcNow;
21-
public DateTime? UpdatedAt { get; private set; }
22-
public DateTime? DeletedAt { get; private set; }
23-
24-
#endregion
25-
2618
#region Overrides
2719

2820
public override int GetHashCode()
@@ -51,16 +43,6 @@ public void RaiseEvent(IDomainEvent @event)
5143

5244
#endregion
5345

54-
#region BaseEntity Methods
55-
56-
public void UpdateEntity()
57-
=> UpdatedAt = DateTime.UtcNow;
58-
59-
public void DeleteEntity()
60-
=> DeletedAt = DateTime.UtcNow;
61-
62-
#endregion
63-
6446
#region Operators
6547

6648
public static bool operator ==(BaseEntity? left, BaseEntity? right)

src/Riber.Infrastructure/Persistence/Interceptors/AuditInterceptor.cs

Lines changed: 6 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
using Microsoft.EntityFrameworkCore;
22
using Microsoft.EntityFrameworkCore.Diagnostics;
3+
using Riber.Domain.Abstractions;
34
using Riber.Domain.Entities;
45
using Riber.Infrastructure.Persistence.Identity;
5-
using Riber.Infrastructure.Persistence.Models;
66

77
namespace Riber.Infrastructure.Persistence.Interceptors;
88

@@ -23,10 +23,7 @@ public override InterceptionResult<int> SavingChanges(
2323
InterceptionResult<int> result)
2424
{
2525
if (eventData.Context is not null)
26-
{
27-
ApplyAuditEntities(eventData.Context);
28-
ApplyAuditModels(eventData.Context);
29-
}
26+
ApplyAuditTracker(eventData.Context);
3027

3128
return base.SavingChanges(eventData, result);
3229
}
@@ -37,20 +34,20 @@ public override ValueTask<InterceptionResult<int>> SavingChangesAsync(
3734
CancellationToken cancellationToken = default)
3835
{
3936
if (eventData.Context is not null)
40-
ApplyAuditEntities(eventData.Context);
37+
ApplyAuditTracker(eventData.Context);
4138

4239
return base.SavingChangesAsync(eventData, result, cancellationToken);
4340
}
4441

4542
/// <summary>
46-
/// Aplica lógica de auditoria às entidades rastreadas pelo contexto do Entity Framework Core.
43+
/// Aplica lógica de auditoria às trackers rastreadas pelo contexto do Entity Framework Core.
4744
/// Atualiza os timestamps de modificação ou realiza ações específicas para estados de entidade,
4845
/// como exclusões suaves.
4946
/// </summary>
5047
/// <param name="context">O contexto do banco de dados que contém o rastreador de alterações para as entidades alvo.</param>
51-
private static void ApplyAuditEntities(DbContext context)
48+
private static void ApplyAuditTracker(DbContext context)
5249
{
53-
var entries = context.ChangeTracker.Entries<BaseEntity>();
50+
var entries = context.ChangeTracker.Entries<Tracker>();
5451
foreach (var entry in entries)
5552
{
5653
if (entry.State is EntityState.Modified)
@@ -67,22 +64,6 @@ private static void ApplyAuditEntities(DbContext context)
6764
}
6865
}
6966

70-
private static void ApplyAuditModels(DbContext context)
71-
{
72-
var entries = context.ChangeTracker.Entries<BaseModel>();
73-
foreach (var entry in entries)
74-
{
75-
if (entry.State is EntityState.Modified)
76-
entry.Entity.UpdatedAt = DateTime.UtcNow;
77-
78-
if (entry.State is EntityState.Deleted)
79-
{
80-
entry.State = EntityState.Modified;
81-
entry.Entity.DeletedAt = DateTime.UtcNow;
82-
}
83-
}
84-
}
85-
8667
/// <summary>
8768
/// Desativa um usuário da aplicação marcando-o como excluído e define
8869
/// o estado da entidade como Modificado no contexto do banco de dados fornecido.
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
using Microsoft.EntityFrameworkCore;
2+
using Microsoft.EntityFrameworkCore.Metadata.Builders;
3+
using Riber.Domain.Abstractions;
4+
5+
namespace Riber.Infrastructure.Persistence.Mappings;
6+
7+
public abstract class BaseTypeConfiguration<T> : IEntityTypeConfiguration<T>
8+
where T : Tracker
9+
{
10+
public void Configure(EntityTypeBuilder<T> builder)
11+
{
12+
builder.ToTable(GetTableName());
13+
14+
builder.HasKey(x => x.Id)
15+
.HasName($"pk_{GetTableName()}_id");
16+
17+
builder.Property(x => x.Id)
18+
.HasColumnName("id")
19+
.HasColumnType("uuid")
20+
.IsRequired();
21+
22+
builder.Property(x => x.CreatedAt)
23+
.HasColumnName("created_at")
24+
.HasColumnType("timestamptz")
25+
.IsRequired();
26+
27+
builder.Property(x => x.UpdatedAt)
28+
.HasColumnName("modified_at")
29+
.HasColumnType("timestamptz");
30+
31+
builder.Property(x => x.DeletedAt)
32+
.HasColumnName("deleted_at")
33+
.HasColumnType("timestamptz");
34+
35+
Mapping(builder);
36+
ConfigureQueryFilter(builder);
37+
}
38+
39+
/// <summary>
40+
/// Obtém o nome da tabela no banco de dados para o tipo mapeado.
41+
/// </summary>
42+
/// <returns>
43+
/// O nome da tabela correspondente.
44+
/// </returns>
45+
protected abstract string GetTableName();
46+
47+
/// <summary>
48+
/// Aplica configurações específicas de mapeamento para o tipo.
49+
/// Sobrescreva este método para definir mapeamentos de propriedades, relações e outras configurações personalizadas.
50+
/// </summary>
51+
/// <param name="builder">
52+
/// O construtor de configuração do tipo de entidade.
53+
/// </param>
54+
protected abstract void Mapping(EntityTypeBuilder<T> builder);
55+
56+
/// <summary>
57+
/// Configura filtros de consulta globais para o tipo.
58+
/// Por padrão, aplica um filtro para excluir registros marcados como deletados.
59+
/// Sobrescreva este método para implementar filtros adicionais ou personalizados.
60+
/// </summary>
61+
/// <param name="builder">
62+
/// O construtor de configuração do tipo de entidade.
63+
/// </param>
64+
protected virtual void ConfigureQueryFilter(EntityTypeBuilder<T> builder)
65+
=> builder.HasQueryFilter(x => !x.DeletedAt.HasValue);
66+
}

src/Riber.Infrastructure/Persistence/Mappings/Entities/BaseEntityConfiguration.cs

Lines changed: 0 additions & 82 deletions
This file was deleted.

src/Riber.Infrastructure/Persistence/Mappings/Entities/CompanyMap.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@
44

55
namespace Riber.Infrastructure.Persistence.Mappings.Entities;
66

7-
public sealed class CompanyMap : BaseEntityConfiguration<Company>
7+
public sealed class CompanyMap : BaseTypeConfiguration<Company>
88
{
99
protected override string GetTableName()
1010
=> "company";
1111

12-
protected override void ConfigureEntity(EntityTypeBuilder<Company> builder)
12+
protected override void Mapping(EntityTypeBuilder<Company> builder)
1313
{
1414
builder
1515
.ConfigureTaxId("uq_company_tax_id")

src/Riber.Infrastructure/Persistence/Mappings/Entities/ImageMap.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55

66
namespace Riber.Infrastructure.Persistence.Mappings.Entities;
77

8-
public sealed class ImageMap : BaseEntityConfiguration<Image>
8+
public sealed class ImageMap : BaseTypeConfiguration<Image>
99
{
1010
protected override string GetTableName()
1111
=> "image";
1212

13-
protected override void ConfigureEntity(EntityTypeBuilder<Image> builder)
13+
protected override void Mapping(EntityTypeBuilder<Image> builder)
1414
{
1515
builder.ConfigureContentType();
1616

src/Riber.Infrastructure/Persistence/Mappings/Entities/InvitationMap.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55

66
namespace Riber.Infrastructure.Persistence.Mappings.Entities;
77

8-
public sealed class InvitationMap : BaseEntityConfiguration<Invitation>
8+
public sealed class InvitationMap : BaseTypeConfiguration<Invitation>
99
{
1010
protected override string GetTableName()
1111
=> "invitation";
1212

13-
protected override void ConfigureEntity(EntityTypeBuilder<Invitation> builder)
13+
protected override void Mapping(EntityTypeBuilder<Invitation> builder)
1414
{
1515
builder
1616
.ConfigureEmail("uq_invitations_email")

0 commit comments

Comments
 (0)