diff --git a/Directory.Build.props b/Directory.Build.props
new file mode 100644
index 0000000..e42216a
--- /dev/null
+++ b/Directory.Build.props
@@ -0,0 +1,5 @@
+
+
+ true
+
+
diff --git a/Directory.Packages.props b/Directory.Packages.props
new file mode 100644
index 0000000..4137eeb
--- /dev/null
+++ b/Directory.Packages.props
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/HrynCo.NotificationService.Api.IntegrationTests/HrynCo.NotificationService.Api.IntegrationTests.csproj b/HrynCo.NotificationService.Api.IntegrationTests/HrynCo.NotificationService.Api.IntegrationTests.csproj
index 51b03d1..35be975 100644
--- a/HrynCo.NotificationService.Api.IntegrationTests/HrynCo.NotificationService.Api.IntegrationTests.csproj
+++ b/HrynCo.NotificationService.Api.IntegrationTests/HrynCo.NotificationService.Api.IntegrationTests.csproj
@@ -1,4 +1,4 @@
-
+
net10.0
@@ -8,10 +8,10 @@
-
-
-
-
+
+
+
+
diff --git a/HrynCo.NotificationService.Api/HrynCo.NotificationService.Api.csproj b/HrynCo.NotificationService.Api/HrynCo.NotificationService.Api.csproj
index af153da..ef39b79 100644
--- a/HrynCo.NotificationService.Api/HrynCo.NotificationService.Api.csproj
+++ b/HrynCo.NotificationService.Api/HrynCo.NotificationService.Api.csproj
@@ -7,7 +7,7 @@
-
+
diff --git a/HrynCo.NotificationService.DAL.EF/Configurations/ProviderEntityConfiguration.cs b/HrynCo.NotificationService.DAL.EF/Configurations/ProviderEntityConfiguration.cs
new file mode 100644
index 0000000..4d584c9
--- /dev/null
+++ b/HrynCo.NotificationService.DAL.EF/Configurations/ProviderEntityConfiguration.cs
@@ -0,0 +1,39 @@
+using HrynCo.NotificationService.DAL.EF.Entities;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+
+namespace HrynCo.NotificationService.DAL.EF.Configurations;
+
+internal class ProviderEntityConfiguration : IEntityTypeConfiguration
+{
+ public void Configure(EntityTypeBuilder builder)
+ {
+ builder.ToTable("providers");
+
+ builder.HasKey(x => x.Id);
+ builder.Property(x => x.Id).HasColumnName("id");
+
+ builder.Property(x => x.ServiceName)
+ .HasColumnName("service_name")
+ .IsRequired()
+ .HasMaxLength(100);
+
+ builder.HasIndex(x => new { x.ServiceName, x.Priority });
+
+ builder.Property(x => x.Priority).HasColumnName("priority");
+
+ builder.Property(x => x.ProviderType).HasColumnName("provider_type");
+
+ builder.Property(x => x.SettingsJson)
+ .HasColumnName("settings")
+ .HasColumnType("jsonb")
+ .IsRequired();
+
+ builder.Property(x => x.DailyLimit).HasColumnName("daily_limit");
+ builder.Property(x => x.MonthlyLimit).HasColumnName("monthly_limit");
+ builder.Property(x => x.WarnThresholdPercent).HasColumnName("warn_threshold_percent");
+ builder.Property(x => x.IsActive).HasColumnName("is_active");
+ builder.Property(x => x.Created).HasColumnName("created");
+ builder.Property(x => x.Updated).HasColumnName("updated");
+ }
+}
diff --git a/HrynCo.NotificationService.DAL.EF/Configurations/ProviderUsageEntityConfiguration.cs b/HrynCo.NotificationService.DAL.EF/Configurations/ProviderUsageEntityConfiguration.cs
new file mode 100644
index 0000000..b2ac7ff
--- /dev/null
+++ b/HrynCo.NotificationService.DAL.EF/Configurations/ProviderUsageEntityConfiguration.cs
@@ -0,0 +1,25 @@
+using HrynCo.NotificationService.DAL.EF.Entities;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+
+namespace HrynCo.NotificationService.DAL.EF.Configurations;
+
+internal class ProviderUsageEntityConfiguration : IEntityTypeConfiguration
+{
+ public void Configure(EntityTypeBuilder builder)
+ {
+ builder.ToTable("provider_usage");
+
+ builder.HasKey(x => x.Id);
+ builder.Property(x => x.Id).HasColumnName("id");
+
+ builder.Property(x => x.ProviderId).HasColumnName("provider_id");
+
+ builder.HasIndex(x => new { x.ProviderId, x.Date }).IsUnique();
+
+ builder.Property(x => x.Date).HasColumnName("date");
+ builder.Property(x => x.SentCount).HasColumnName("sent_count");
+ builder.Property(x => x.Created).HasColumnName("created");
+ builder.Property(x => x.Updated).HasColumnName("updated");
+ }
+}
diff --git a/HrynCo.NotificationService.DAL.EF/Configurations/TemplateEntityConfiguration.cs b/HrynCo.NotificationService.DAL.EF/Configurations/TemplateEntityConfiguration.cs
new file mode 100644
index 0000000..ed49681
--- /dev/null
+++ b/HrynCo.NotificationService.DAL.EF/Configurations/TemplateEntityConfiguration.cs
@@ -0,0 +1,56 @@
+using HrynCo.NotificationService.DAL.EF.Entities;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+
+namespace HrynCo.NotificationService.DAL.EF.Configurations;
+
+internal class TemplateEntityConfiguration : IEntityTypeConfiguration
+{
+ public void Configure(EntityTypeBuilder builder)
+ {
+ builder.ToTable("templates");
+
+ builder.HasKey(x => x.Id);
+ builder.Property(x => x.Id).HasColumnName("id");
+
+ builder.Property(x => x.ServiceName)
+ .HasColumnName("service_name")
+ .IsRequired()
+ .HasMaxLength(100);
+
+ builder.Property(x => x.Key)
+ .HasColumnName("key")
+ .IsRequired()
+ .HasMaxLength(100);
+
+ builder.Property(x => x.LanguageCode)
+ .HasColumnName("language_code")
+ .IsRequired()
+ .HasMaxLength(10);
+
+ builder.HasIndex(x => new { x.ServiceName, x.Key, x.LanguageCode })
+ .IsUnique();
+
+ builder.Property(x => x.Subject)
+ .HasColumnName("subject")
+ .IsRequired();
+
+ builder.Property(x => x.HtmlBody)
+ .HasColumnName("html_body")
+ .IsRequired();
+
+ builder.Property(x => x.TextBody)
+ .HasColumnName("text_body")
+ .IsRequired();
+
+ builder.Property(x => x.Created).HasColumnName("created");
+ builder.Property(x => x.Updated).HasColumnName("updated");
+
+ builder.OwnsMany(x => x.Variables, v =>
+ {
+ v.ToJson("variables");
+ v.Property(x => x.Name).HasJsonPropertyName("name");
+ v.Property(x => x.Required).HasJsonPropertyName("required");
+ });
+ }
+}
diff --git a/HrynCo.NotificationService.DAL.EF/Entities/ProviderEntity.cs b/HrynCo.NotificationService.DAL.EF/Entities/ProviderEntity.cs
new file mode 100644
index 0000000..1101ef1
--- /dev/null
+++ b/HrynCo.NotificationService.DAL.EF/Entities/ProviderEntity.cs
@@ -0,0 +1,24 @@
+using HrynCo.NotificationService.DAL.Abstract.Providers;
+
+namespace HrynCo.NotificationService.DAL.EF.Entities;
+
+internal class ProviderEntity
+{
+ public Guid Id { get; set; }
+ public required string ServiceName { get; set; }
+ public int Priority { get; set; }
+ public ProviderType ProviderType { get; set; }
+
+ ///
+ /// Provider-specific credentials and settings stored as JSONB.
+ /// Deserialized based on in the repository.
+ ///
+ public required string SettingsJson { get; set; }
+
+ public int? DailyLimit { get; set; }
+ public int? MonthlyLimit { get; set; }
+ public int WarnThresholdPercent { get; set; }
+ public bool IsActive { get; set; }
+ public DateTimeOffset Created { get; set; }
+ public DateTimeOffset? Updated { get; set; }
+}
diff --git a/HrynCo.NotificationService.DAL.EF/Entities/ProviderUsageEntity.cs b/HrynCo.NotificationService.DAL.EF/Entities/ProviderUsageEntity.cs
new file mode 100644
index 0000000..dbce792
--- /dev/null
+++ b/HrynCo.NotificationService.DAL.EF/Entities/ProviderUsageEntity.cs
@@ -0,0 +1,11 @@
+namespace HrynCo.NotificationService.DAL.EF.Entities;
+
+internal class ProviderUsageEntity
+{
+ public Guid Id { get; set; }
+ public Guid ProviderId { get; set; }
+ public DateOnly Date { get; set; }
+ public int SentCount { get; set; }
+ public DateTimeOffset Created { get; set; }
+ public DateTimeOffset? Updated { get; set; }
+}
diff --git a/HrynCo.NotificationService.DAL.EF/Entities/TemplateEntity.cs b/HrynCo.NotificationService.DAL.EF/Entities/TemplateEntity.cs
new file mode 100644
index 0000000..ffa132e
--- /dev/null
+++ b/HrynCo.NotificationService.DAL.EF/Entities/TemplateEntity.cs
@@ -0,0 +1,21 @@
+namespace HrynCo.NotificationService.DAL.EF.Entities;
+
+internal class TemplateEntity
+{
+ public Guid Id { get; set; }
+ public required string ServiceName { get; set; }
+ public required string Key { get; set; }
+ public required string LanguageCode { get; set; }
+ public required string Subject { get; set; }
+ public required string HtmlBody { get; set; }
+ public required string TextBody { get; set; }
+ public List Variables { get; set; } = [];
+ public DateTimeOffset Created { get; set; }
+ public DateTimeOffset? Updated { get; set; }
+}
+
+internal class TemplateVariableData
+{
+ public required string Name { get; set; }
+ public bool Required { get; set; }
+}
diff --git a/HrynCo.NotificationService.DAL.EF/HrynCo.NotificationService.DAL.EF.csproj b/HrynCo.NotificationService.DAL.EF/HrynCo.NotificationService.DAL.EF.csproj
index 8011d57..f073f56 100644
--- a/HrynCo.NotificationService.DAL.EF/HrynCo.NotificationService.DAL.EF.csproj
+++ b/HrynCo.NotificationService.DAL.EF/HrynCo.NotificationService.DAL.EF.csproj
@@ -4,6 +4,16 @@
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
net10.0
enable
diff --git a/HrynCo.NotificationService.DAL.EF/NotificationDbContext.cs b/HrynCo.NotificationService.DAL.EF/NotificationDbContext.cs
new file mode 100644
index 0000000..2ff4c34
--- /dev/null
+++ b/HrynCo.NotificationService.DAL.EF/NotificationDbContext.cs
@@ -0,0 +1,21 @@
+using HrynCo.NotificationService.DAL.EF.Entities;
+using Microsoft.EntityFrameworkCore;
+
+namespace HrynCo.NotificationService.DAL.EF;
+
+public class NotificationDbContext : DbContext
+{
+ public NotificationDbContext(DbContextOptions options)
+ : base(options)
+ {
+ }
+
+ internal DbSet Templates => Set();
+ internal DbSet Providers => Set();
+ internal DbSet ProviderUsage => Set();
+
+ protected override void OnModelCreating(ModelBuilder modelBuilder)
+ {
+ modelBuilder.ApplyConfigurationsFromAssembly(typeof(NotificationDbContext).Assembly);
+ }
+}
diff --git a/HrynCo.NotificationService.Services.Tests/HrynCo.NotificationService.Services.Tests.csproj b/HrynCo.NotificationService.Services.Tests/HrynCo.NotificationService.Services.Tests.csproj
index 90aa85b..69e51f0 100644
--- a/HrynCo.NotificationService.Services.Tests/HrynCo.NotificationService.Services.Tests.csproj
+++ b/HrynCo.NotificationService.Services.Tests/HrynCo.NotificationService.Services.Tests.csproj
@@ -1,4 +1,4 @@
-
+
net10.0
@@ -8,10 +8,10 @@
-
-
-
-
+
+
+
+
diff --git a/HrynCo.NotificationService.Worker/HrynCo.NotificationService.Worker.csproj b/HrynCo.NotificationService.Worker/HrynCo.NotificationService.Worker.csproj
index e044c6a..8f82f22 100644
--- a/HrynCo.NotificationService.Worker/HrynCo.NotificationService.Worker.csproj
+++ b/HrynCo.NotificationService.Worker/HrynCo.NotificationService.Worker.csproj
@@ -8,7 +8,7 @@
-
+