using ElectionSystem.Api.Infrastructure.Auditing; using ElectionSystem.Api.Modules.Identity.Domain; using ElectionSystem.Api.Modules.Organization.Domain; using ElectionSystem.Api.Modules.Voters.Domain; using ElectionSystem.Api.Modules.Candidates.Domain; using Microsoft.EntityFrameworkCore; namespace ElectionSystem.Api.Infrastructure.Persistence; public sealed class ElectionDbContext(DbContextOptions options) : DbContext(options) { public DbSet Users => Set(); public DbSet OrganizationUnits => Set(); public DbSet AdministrativeRegions => Set(); public DbSet UserRegionalRoleAssignments => Set(); public DbSet CountingStations => Set(); public DbSet UserCountingStationAssignments => Set(); public DbSet Voters => Set(); public DbSet Candidates => Set(); public DbSet AuditEntries => Set(); protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity(entity => { entity.ToTable("identity_users"); entity.Property(x => x.UserName).HasMaxLength(128).IsRequired(); entity.Property(x => x.DisplayName).HasMaxLength(128).IsRequired(); entity.Property(x => x.ExternalSubject).HasMaxLength(256); entity.HasIndex(x => x.UserName).IsUnique(); entity.HasIndex(x => x.ExternalSubject).IsUnique(); }); modelBuilder.Entity(entity => { entity.ToTable("administrative_regions"); entity.Property(x => x.Code).HasMaxLength(32).IsRequired(); entity.Property(x => x.Name).HasMaxLength(200).IsRequired(); entity.Property(x => x.Source).HasMaxLength(128).IsRequired(); entity.Property(x => x.SourceVersion).HasMaxLength(64).IsRequired(); entity.HasIndex(x => new { x.Code, x.SourceVersion }).IsUnique(); entity.HasIndex(x => new { x.ParentId, x.Level, x.IsActive }); entity.HasOne().WithMany().HasForeignKey(x => x.ParentId).OnDelete(DeleteBehavior.Restrict); }); modelBuilder.Entity(entity => { entity.ToTable("identity_user_regional_roles"); entity.HasIndex(x => new { x.UserId, x.Role, x.RegionId }).IsUnique(); entity.HasOne().WithMany().HasForeignKey(x => x.UserId).OnDelete(DeleteBehavior.Cascade); entity.HasOne().WithMany().HasForeignKey(x => x.RegionId).OnDelete(DeleteBehavior.Restrict); }); modelBuilder.Entity(entity => { entity.ToTable("counting_stations"); entity.Property(x => x.Name).HasMaxLength(200).IsRequired(); entity.Property(x => x.Code).HasMaxLength(64).IsRequired(); entity.HasIndex(x => x.Code).IsUnique(); entity.HasIndex(x => x.RegionId); entity.HasOne().WithMany().HasForeignKey(x => x.RegionId).OnDelete(DeleteBehavior.Restrict); }); modelBuilder.Entity(entity => { entity.ToTable("identity_user_counting_stations"); entity.HasIndex(x => new { x.UserId, x.CountingStationId }).IsUnique(); entity.HasOne().WithMany().HasForeignKey(x => x.UserId).OnDelete(DeleteBehavior.Cascade); entity.HasOne().WithMany().HasForeignKey(x => x.CountingStationId).OnDelete(DeleteBehavior.Cascade); }); modelBuilder.Entity(entity => { entity.ToTable("voter_profiles"); entity.Property(x => x.VoterNumber).HasMaxLength(64).IsRequired(); entity.Property(x => x.DisplayName).HasMaxLength(128).IsRequired(); entity.Property(x => x.DisabledReason).HasMaxLength(500); entity.HasIndex(x => x.VoterNumber).IsUnique(); entity.HasIndex(x => new { x.RegionId, x.Status, x.DisplayName }); entity.HasIndex(x => x.UserId).IsUnique(); entity.HasOne().WithMany().HasForeignKey(x => x.RegionId).OnDelete(DeleteBehavior.Restrict); entity.HasOne().WithMany().HasForeignKey(x => x.UserId).OnDelete(DeleteBehavior.Restrict); }); modelBuilder.Entity(entity => { entity.ToTable("candidate_profiles"); entity.Property(x => x.DisplayName).HasMaxLength(128).IsRequired(); entity.Property(x => x.NominationSummary).HasMaxLength(4000); entity.Property(x => x.StatusReason).HasMaxLength(500); entity.HasIndex(x => new { x.RegionId, x.Status, x.DisplayName }); entity.HasOne().WithMany().HasForeignKey(x => x.RegionId).OnDelete(DeleteBehavior.Restrict); }); modelBuilder.Entity(entity => { entity.ToTable("organization_units"); entity.Property(x => x.Name).HasMaxLength(200).IsRequired(); entity.Property(x => x.Code).HasMaxLength(64).IsRequired(); entity.HasIndex(x => x.Code).IsUnique(); entity.HasOne().WithMany().HasForeignKey(x => x.ParentId).OnDelete(DeleteBehavior.Restrict); }); modelBuilder.Entity(entity => { entity.ToTable("audit_entries"); entity.Property(x => x.Action).HasMaxLength(128).IsRequired(); entity.Property(x => x.ResourceType).HasMaxLength(128).IsRequired(); entity.Property(x => x.TraceId).HasMaxLength(128); entity.Property(x => x.ActorId).HasMaxLength(128); entity.Property(x => x.MetadataJson).HasColumnType("json"); entity.HasIndex(x => new { x.OccurredAtUtc, x.ResourceType }); }); } }