refactor: rename domain types and introduce TransactionBehavior pattern
- Rename Template -> EmailTemplate, Provider -> EmailChannel, ProviderSettings -> EmailChannelSettings, ProviderType -> EmailChannelType, ProviderUsage -> EmailChannelUsage throughout all layers - Add Undefined = 0 to EmailChannelType enum for safe default handling - Remove SaveChangesAsync from EfRepository methods — repositories now only stage changes - Add SaveChangesAsync to IUnitOfWork and EfUnitOfWork - Add TransactionBehavior MediatR pipeline: wraps every handler in a transaction, saves and commits on success, rolls back on exception - Add MediatR package reference to Services project Ref: IT-628 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -2,6 +2,7 @@ namespace HrynCo.NotificationService.DAL.Abstract;
|
||||
|
||||
public interface IUnitOfWork
|
||||
{
|
||||
Task SaveChangesAsync(CancellationToken cancellationToken = default);
|
||||
Task<ITransaction> BeginTransactionAsync(CancellationToken cancellationToken = default);
|
||||
ITransaction? GetCurrentTransaction();
|
||||
|
||||
|
||||
+4
-4
@@ -2,14 +2,14 @@ using HrynCo.NotificationService.DAL.Abstract.Entities;
|
||||
|
||||
namespace HrynCo.NotificationService.DAL.Abstract.Providers;
|
||||
|
||||
public class Provider : Entity
|
||||
public class EmailChannel : Entity
|
||||
{
|
||||
public required string ServiceName { get; set; }
|
||||
public int Priority { get; set; }
|
||||
public ProviderType ProviderType { get; set; }
|
||||
public required ProviderSettings Settings { get; set; }
|
||||
public EmailChannelType EmailChannelType { get; set; }
|
||||
public required EmailChannelSettings Settings { get; set; }
|
||||
public int? DailyLimit { get; set; }
|
||||
public int? MonthlyLimit { get; set; }
|
||||
public int WarnThresholdPercent { get; set; } = 90;
|
||||
public bool IsActive { get; set; } = true;
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -1,13 +1,13 @@
|
||||
namespace HrynCo.NotificationService.DAL.Abstract.Providers;
|
||||
|
||||
public abstract class ProviderSettings
|
||||
public abstract class EmailChannelSettings
|
||||
{
|
||||
public abstract ProviderType ProviderType { get; }
|
||||
public abstract EmailChannelType EmailChannelType { get; }
|
||||
}
|
||||
|
||||
public class SmtpProviderSettings : ProviderSettings
|
||||
public class SmtpChannelSettings : EmailChannelSettings
|
||||
{
|
||||
public override ProviderType ProviderType => ProviderType.Smtp;
|
||||
public override EmailChannelType EmailChannelType => EmailChannelType.Smtp;
|
||||
|
||||
public required string Host { get; set; }
|
||||
public int Port { get; set; } = 587;
|
||||
+2
-1
@@ -1,6 +1,7 @@
|
||||
namespace HrynCo.NotificationService.DAL.Abstract.Providers;
|
||||
|
||||
public enum ProviderType
|
||||
public enum EmailChannelType
|
||||
{
|
||||
Undefined = 0,
|
||||
Smtp = 1
|
||||
}
|
||||
+2
-2
@@ -3,10 +3,10 @@ using HrynCo.NotificationService.DAL.Abstract.Entities;
|
||||
namespace HrynCo.NotificationService.DAL.Abstract.Providers;
|
||||
|
||||
/// <summary>
|
||||
/// Tracks email send counts per provider per calendar day.
|
||||
/// Tracks email send counts per EmailChannel per calendar day.
|
||||
/// Monthly counts are derived by summing daily records within a month.
|
||||
/// </summary>
|
||||
public class ProviderUsage : Entity
|
||||
public class EmailChannelUsage : Entity
|
||||
{
|
||||
public Guid ProviderId { get; set; }
|
||||
public DateOnly Date { get; set; }
|
||||
@@ -0,0 +1,12 @@
|
||||
using HrynCo.NotificationService.DAL.Abstract.Providers;
|
||||
|
||||
namespace HrynCo.NotificationService.DAL.Abstract.Repositories;
|
||||
|
||||
public interface IEmailChannelRepository
|
||||
{
|
||||
Task<IReadOnlyList<EmailChannel>> GetByServiceAsync(string serviceName, CancellationToken ct = default);
|
||||
Task<EmailChannel?> GetByIdAsync(Guid id, CancellationToken ct = default);
|
||||
Task AddAsync(EmailChannel channel, CancellationToken ct = default);
|
||||
Task UpdateAsync(EmailChannel channel, CancellationToken ct = default);
|
||||
Task DeleteAsync(EmailChannel channel, CancellationToken ct = default);
|
||||
}
|
||||
+2
-2
@@ -2,9 +2,9 @@ using HrynCo.NotificationService.DAL.Abstract.Providers;
|
||||
|
||||
namespace HrynCo.NotificationService.DAL.Abstract.Repositories;
|
||||
|
||||
public interface IProviderUsageRepository
|
||||
public interface IEmailChannelUsageRepository
|
||||
{
|
||||
Task<int> GetDailyCountAsync(Guid providerId, DateOnly date, CancellationToken ct = default);
|
||||
Task<int> GetMonthlyCountAsync(Guid providerId, int year, int month, CancellationToken ct = default);
|
||||
Task IncrementAsync(Guid providerId, DateOnly date, CancellationToken ct = default);
|
||||
Task IncrementUsageAsync(Guid providerId, DateOnly date, CancellationToken ct = default);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using HrynCo.NotificationService.DAL.Abstract.Templates;
|
||||
|
||||
namespace HrynCo.NotificationService.DAL.Abstract.Repositories;
|
||||
|
||||
public interface IEmailEmailTemplateRepository
|
||||
{
|
||||
Task<IReadOnlyList<EmailTemplate>> GetByServiceAsync(string serviceName, CancellationToken ct = default);
|
||||
Task<EmailTemplate?> GetAsync(string serviceName, string key, string languageCode, CancellationToken ct = default);
|
||||
Task AddAsync(EmailTemplate EmailTemplate, CancellationToken ct = default);
|
||||
Task UpdateAsync(EmailTemplate EmailTemplate, CancellationToken ct = default);
|
||||
Task DeleteAsync(EmailTemplate EmailTemplate, CancellationToken ct = default);
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
using HrynCo.NotificationService.DAL.Abstract.Providers;
|
||||
|
||||
namespace HrynCo.NotificationService.DAL.Abstract.Repositories;
|
||||
|
||||
public interface IProviderRepository
|
||||
{
|
||||
Task<IReadOnlyList<Provider>> GetByServiceAsync(string serviceName, CancellationToken ct = default);
|
||||
Task<Provider?> GetByIdAsync(Guid id, CancellationToken ct = default);
|
||||
Task AddAsync(Provider provider, CancellationToken ct = default);
|
||||
Task UpdateAsync(Provider provider, CancellationToken ct = default);
|
||||
Task DeleteAsync(Provider provider, CancellationToken ct = default);
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
using HrynCo.NotificationService.DAL.Abstract.Templates;
|
||||
|
||||
namespace HrynCo.NotificationService.DAL.Abstract.Repositories;
|
||||
|
||||
public interface ITemplateRepository
|
||||
{
|
||||
Task<IReadOnlyList<Template>> GetByServiceAsync(string serviceName, CancellationToken ct = default);
|
||||
Task<Template?> GetAsync(string serviceName, string key, string languageCode, CancellationToken ct = default);
|
||||
Task AddAsync(Template template, CancellationToken ct = default);
|
||||
Task UpdateAsync(Template template, CancellationToken ct = default);
|
||||
Task DeleteAsync(Template template, CancellationToken ct = default);
|
||||
}
|
||||
+2
-2
@@ -2,7 +2,7 @@ using HrynCo.NotificationService.DAL.Abstract.Entities;
|
||||
|
||||
namespace HrynCo.NotificationService.DAL.Abstract.Templates;
|
||||
|
||||
public class Template : Entity
|
||||
public class EmailTemplate : Entity
|
||||
{
|
||||
public required string ServiceName { get; set; }
|
||||
public required string Key { get; set; }
|
||||
@@ -10,5 +10,5 @@ public class Template : Entity
|
||||
public required string Subject { get; set; }
|
||||
public required string HtmlBody { get; set; }
|
||||
public required string TextBody { get; set; }
|
||||
public IReadOnlyList<TemplateVariable> Variables { get; set; } = [];
|
||||
public IReadOnlyList<EmailTemplateVariable> Variables { get; set; } = [];
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace HrynCo.NotificationService.DAL.Abstract.Templates;
|
||||
|
||||
public record TemplateVariable
|
||||
public record EmailTemplateVariable
|
||||
{
|
||||
public required string Name { get; init; }
|
||||
public bool Required { get; init; }
|
||||
|
||||
Reference in New Issue
Block a user