投票发布功能

This commit is contained in:
biss committed 2026-08-29 21:42:31 +08:00
1 parent ae9e8e0c9d
commit 1e0652211b
24 files changed
+3633 -7

No files matched your search

@@ -3,6 +3,8 @@ 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 ElectionSystem.Api.Modules.Election.Domain;
using ElectionSystem.Api.Modules.OfflineCounting.Domain;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity;
@@ -18,6 +20,13 @@ public sealed class ElectionDbContext(DbContextOptions<ElectionDbContext> option
public DbSet<UserCountingStationAssignment> UserCountingStationAssignments => Set<UserCountingStationAssignment>();
public DbSet<VoterProfile> Voters => Set<VoterProfile>();
public DbSet<CandidateProfile> Candidates => Set<CandidateProfile>();
public DbSet<ElectionActivity> ElectionActivities => Set<ElectionActivity>();
public DbSet<ElectionContest> ElectionContests => Set<ElectionContest>();
public DbSet<ElectionOption> ElectionOptions => Set<ElectionOption>();
public DbSet<ElectionCountingStation> ElectionCountingStations => Set<ElectionCountingStation>();
public DbSet<OfflineCountingSession> OfflineCountingSessions => Set<OfflineCountingSession>();
public DbSet<OfflineCountSubmission> OfflineCountSubmissions => Set<OfflineCountSubmission>();
public DbSet<OfflineCountTally> OfflineCountTallies => Set<OfflineCountTally>();
public DbSet<AuditEntry> AuditEntries => Set<AuditEntry>();
protected override void OnModelCreating(ModelBuilder modelBuilder)
@@ -101,6 +110,62 @@ public sealed class ElectionDbContext(DbContextOptions<ElectionDbContext> option
entity.HasIndex(x => x.Code).IsUnique();
entity.HasOne<OrganizationUnit>().WithMany().HasForeignKey(x => x.ParentId).OnDelete(DeleteBehavior.Restrict);
});
modelBuilder.Entity<ElectionActivity>(entity =>
{
entity.ToTable("election_activities");
entity.Property(x => x.Name).HasMaxLength(200).IsRequired();
entity.Property(x => x.Description).HasMaxLength(4000);
entity.HasIndex(x => new { x.RegionId, x.Status, x.VotingEndsAtUtc });
entity.HasOne<AdministrativeRegion>().WithMany().HasForeignKey(x => x.RegionId).OnDelete(DeleteBehavior.Restrict);
});
modelBuilder.Entity<ElectionContest>(entity =>
{
entity.ToTable("election_contests");
entity.Property(x => x.Title).HasMaxLength(200).IsRequired();
entity.Property(x => x.RequiredSupportPercent).HasPrecision(5, 2);
entity.HasIndex(x => new { x.ElectionActivityId, x.SortOrder }).IsUnique();
entity.HasOne<ElectionActivity>().WithMany().HasForeignKey(x => x.ElectionActivityId).OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity<ElectionOption>(entity =>
{
entity.ToTable("election_options");
entity.Property(x => x.Label).HasMaxLength(200).IsRequired();
entity.HasIndex(x => new { x.ElectionContestId, x.SortOrder }).IsUnique();
entity.HasIndex(x => new { x.ElectionContestId, x.CandidateId }).IsUnique();
entity.HasOne<ElectionContest>().WithMany().HasForeignKey(x => x.ElectionContestId).OnDelete(DeleteBehavior.Cascade);
entity.HasOne<CandidateProfile>().WithMany().HasForeignKey(x => x.CandidateId).OnDelete(DeleteBehavior.Restrict);
});
modelBuilder.Entity<ElectionCountingStation>(entity =>
{
entity.ToTable("election_counting_stations");
entity.HasKey(x => new { x.ElectionActivityId, x.CountingStationId });
entity.HasOne<ElectionActivity>().WithMany().HasForeignKey(x => x.ElectionActivityId).OnDelete(DeleteBehavior.Cascade);
entity.HasOne<CountingStation>().WithMany().HasForeignKey(x => x.CountingStationId).OnDelete(DeleteBehavior.Restrict);
});
modelBuilder.Entity<OfflineCountingSession>(entity =>
{
entity.ToTable("offline_counting_sessions");
entity.Property(x => x.CorrectionReason).HasMaxLength(1000);
entity.HasIndex(x => new { x.ElectionActivityId, x.CountingStationId, x.Version }).IsUnique();
entity.HasIndex(x => new { x.ElectionActivityId, x.CountingStationId, x.Status });
entity.HasOne<ElectionActivity>().WithMany().HasForeignKey(x => x.ElectionActivityId).OnDelete(DeleteBehavior.Restrict);
entity.HasOne<CountingStation>().WithMany().HasForeignKey(x => x.CountingStationId).OnDelete(DeleteBehavior.Restrict);
entity.HasOne<OfflineCountingSession>().WithMany().HasForeignKey(x => x.ReplacesSessionId).OnDelete(DeleteBehavior.Restrict);
});
modelBuilder.Entity<OfflineCountSubmission>(entity =>
{
entity.ToTable("offline_count_submissions");
entity.HasIndex(x => new { x.OfflineCountingSessionId, x.EnteredByUserId }).IsUnique();
entity.HasOne<OfflineCountingSession>().WithMany().HasForeignKey(x => x.OfflineCountingSessionId).OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity<OfflineCountTally>(entity =>
{
entity.ToTable("offline_count_tallies");
entity.HasIndex(x => new { x.OfflineCountSubmissionId, x.ElectionContestId, x.ElectionOptionId }).IsUnique();
entity.HasOne<OfflineCountSubmission>().WithMany().HasForeignKey(x => x.OfflineCountSubmissionId).OnDelete(DeleteBehavior.Cascade);
entity.HasOne<ElectionContest>().WithMany().HasForeignKey(x => x.ElectionContestId).OnDelete(DeleteBehavior.Restrict);
entity.HasOne<ElectionOption>().WithMany().HasForeignKey(x => x.ElectionOptionId).OnDelete(DeleteBehavior.Restrict);
});
modelBuilder.Entity<AuditEntry>(entity =>
{
entity.ToTable("audit_entries");