feat(viewer): add FreePackClaims owned collection for daily-free quota tracking
This commit is contained in:
4217
SVSim.Database/Migrations/20260609013234_AddViewerFreePackClaims.Designer.cs
generated
Normal file
4217
SVSim.Database/Migrations/20260609013234_AddViewerFreePackClaims.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace SVSim.Database.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddViewerFreePackClaims : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "ViewerFreePackClaim",
|
||||
columns: table => new
|
||||
{
|
||||
FreeGachaCampaignId = table.Column<int>(type: "integer", nullable: false),
|
||||
ViewerId = table.Column<long>(type: "bigint", nullable: false),
|
||||
ClaimCount = table.Column<int>(type: "integer", nullable: false),
|
||||
LastClaimedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_ViewerFreePackClaim", x => new { x.ViewerId, x.FreeGachaCampaignId });
|
||||
table.ForeignKey(
|
||||
name: "FK_ViewerFreePackClaim_Viewers_ViewerId",
|
||||
column: x => x.ViewerId,
|
||||
principalTable: "Viewers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "ViewerFreePackClaim");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3893,6 +3893,28 @@ namespace SVSim.Database.Migrations
|
||||
.HasForeignKey("ViewerId");
|
||||
});
|
||||
|
||||
b.OwnsMany("SVSim.Database.Models.ViewerFreePackClaim", "FreePackClaims", b1 =>
|
||||
{
|
||||
b1.Property<long>("ViewerId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b1.Property<int>("FreeGachaCampaignId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b1.Property<int>("ClaimCount")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b1.Property<DateTime>("LastClaimedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b1.HasKey("ViewerId", "FreeGachaCampaignId");
|
||||
|
||||
b1.ToTable("ViewerFreePackClaim");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("ViewerId");
|
||||
});
|
||||
|
||||
b.OwnsMany("SVSim.Database.Models.ViewerGachaPointBalance", "GachaPointBalances", b1 =>
|
||||
{
|
||||
b1.Property<long>("ViewerId")
|
||||
@@ -4069,6 +4091,8 @@ namespace SVSim.Database.Migrations
|
||||
b.Navigation("Currency")
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("FreePackClaims");
|
||||
|
||||
b.Navigation("GachaPointBalances");
|
||||
|
||||
b.Navigation("GachaPointReceived");
|
||||
|
||||
@@ -65,6 +65,8 @@ public class Viewer : BaseEntity<long>
|
||||
|
||||
public List<ViewerPackOpenCount> PackOpenCounts { get; set; } = new List<ViewerPackOpenCount>();
|
||||
|
||||
public List<ViewerFreePackClaim> FreePackClaims { get; set; } = new List<ViewerFreePackClaim>();
|
||||
|
||||
public List<ViewerGachaPointBalance> GachaPointBalances { get; set; } = new List<ViewerGachaPointBalance>();
|
||||
|
||||
public List<ViewerGachaPointReceived> GachaPointReceived { get; set; } = new List<ViewerGachaPointReceived>();
|
||||
|
||||
15
SVSim.Database/Models/ViewerFreePackClaim.cs
Normal file
15
SVSim.Database/Models/ViewerFreePackClaim.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace SVSim.Database.Models;
|
||||
|
||||
/// <summary>
|
||||
/// One row per (viewer, free_gacha_campaign_id). Counts claims and remembers when the last one
|
||||
/// landed so the controller can gate the daily quota. Owned collection on <see cref="Viewer"/>.
|
||||
/// </summary>
|
||||
[Owned]
|
||||
public class ViewerFreePackClaim
|
||||
{
|
||||
public int FreeGachaCampaignId { get; set; }
|
||||
public int ClaimCount { get; set; }
|
||||
public DateTime LastClaimedAt { get; set; }
|
||||
}
|
||||
@@ -164,6 +164,12 @@ public class SVSimDbContext : DbContext
|
||||
e.HasIndex(x => new { x.PackId, x.Slot, x.Tier });
|
||||
});
|
||||
modelBuilder.Entity<Viewer>().OwnsMany(v => v.PackOpenCounts);
|
||||
modelBuilder.Entity<Viewer>().OwnsMany(v => v.FreePackClaims, b =>
|
||||
{
|
||||
b.WithOwner().HasForeignKey("ViewerId");
|
||||
b.HasKey("ViewerId", nameof(ViewerFreePackClaim.FreeGachaCampaignId));
|
||||
b.Property(x => x.FreeGachaCampaignId).ValueGeneratedNever();
|
||||
});
|
||||
|
||||
// OwnedCardEntry and OwnedItemEntry use composite PK (ViewerId, Id) where Id is auto-
|
||||
// generated, which silently permits multiple rows per (Viewer, Card) or (Viewer, Item).
|
||||
|
||||
Reference in New Issue
Block a user