diff --git a/SVSim.Database/SVSimDbContext.cs b/SVSim.Database/SVSimDbContext.cs index 27ee4d8..0bfc5da 100644 --- a/SVSim.Database/SVSimDbContext.cs +++ b/SVSim.Database/SVSimDbContext.cs @@ -102,6 +102,7 @@ public class SVSimDbContext : DbContext public DbSet ViewerStoryBranchUnlocks => Set(); public DbSet ViewerClaimedTutorialGifts => Set(); + public DbSet ViewerPresents => Set(); public DbSet ArenaTwoPickRewards { get; set; } = null!; public DbSet ViewerArenaTwoPickRuns { get; set; } = null!; @@ -373,6 +374,25 @@ public class SVSimDbContext : DbContext b.Property(g => g.PresentId).HasMaxLength(64); }); + modelBuilder.Entity(b => + { + b.HasKey(p => p.Id); + b.Property(p => p.PresentId).HasMaxLength(64); + b.Property(p => p.Source).HasMaxLength(64); + + b.HasOne(p => p.Viewer) + .WithMany() + .HasForeignKey(p => p.ViewerId) + .OnDelete(DeleteBehavior.Cascade); + + // Drives /gift/top — partition by status, then chronological. + b.HasIndex(p => new { p.ViewerId, p.Status, p.CreatedAt }); + + // One row per (viewer, present_id) — backstop against double-seeding and + // double-enqueue from future producers. + b.HasIndex(p => new { p.ViewerId, p.PresentId }).IsUnique(); + }); + base.OnModelCreating(modelBuilder); }