feat(guild): add Guild aggregate schema + migration
This commit is contained in:
17
SVSim.Database/Entities/Guild/Guild.cs
Normal file
17
SVSim.Database/Entities/Guild/Guild.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using SVSim.Database.Models;
|
||||
|
||||
namespace SVSim.Database.Entities.Guild;
|
||||
|
||||
public class Guild
|
||||
{
|
||||
public int GuildId { get; set; } // server-generated 9-digit
|
||||
public string Name { get; set; } = "";
|
||||
public string Description { get; set; } = "";
|
||||
public long LeaderViewerId { get; set; }
|
||||
public long EmblemId { get; set; }
|
||||
public GuildActivity Activity { get; set; }
|
||||
public GuildJoinCondition JoinCondition { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public DateTime? BreakupAt { get; set; } // soft-delete on breakup
|
||||
public List<GuildMember> Members { get; set; } = new();
|
||||
}
|
||||
16
SVSim.Database/Entities/Guild/GuildChatMessage.cs
Normal file
16
SVSim.Database/Entities/Guild/GuildChatMessage.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
namespace SVSim.Database.Entities.Guild;
|
||||
|
||||
public class GuildChatMessage
|
||||
{
|
||||
public long Id { get; set; } // global PK
|
||||
public int GuildId { get; set; }
|
||||
public int MessageId { get; set; } // per-guild monotonic, unique with GuildId
|
||||
public long AuthorViewerId { get; set; }
|
||||
public GuildChatMessageType MessageType { get; set; }
|
||||
public string Body { get; set; } = "";
|
||||
public string? DeckPayload { get; set; } // jsonb
|
||||
public string? ReplayPayload { get; set; } // jsonb
|
||||
public string? RoomPayload { get; set; } // jsonb
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public Guild Guild { get; set; } = null!;
|
||||
}
|
||||
36
SVSim.Database/Entities/Guild/GuildEnums.cs
Normal file
36
SVSim.Database/Entities/Guild/GuildEnums.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
namespace SVSim.Database.Entities.Guild;
|
||||
|
||||
public enum GuildRole : int
|
||||
{
|
||||
Regular = 0,
|
||||
Leader = 1,
|
||||
SubLeader = 2,
|
||||
}
|
||||
|
||||
public enum GuildJoinCondition : int
|
||||
{
|
||||
Free = 1,
|
||||
Approval = 2,
|
||||
OnlyInvite = 3,
|
||||
}
|
||||
|
||||
// Matches GuildDetailInfo.ActivityType (1..16). All / Beginner / Enjoy / Stoic / FriendOnly /
|
||||
// per-class (Elf..Nemesis) / Rotation / Unlimited / TwoPick.
|
||||
public enum GuildActivity : int
|
||||
{
|
||||
All = 1, Beginner = 2, Enjoy = 3, Stoic = 4, FriendOnly = 5,
|
||||
Elf = 6, Royal = 7, Witch = 8, Dragon = 9, Necro = 10,
|
||||
Vampire = 11, Bishop = 12, Nemesis = 13,
|
||||
Rotation = 14, Unlimited = 15, TwoPick = 16,
|
||||
}
|
||||
|
||||
public enum GuildInviteStatus : int { Pending = 0, Canceled = 1, Rejected = 2, Consumed = 3 }
|
||||
public enum GuildJoinRequestStatus : int { Pending = 0, Canceled = 1, Rejected = 2, Accepted = 3 }
|
||||
|
||||
// Per docs/api-spec/.../guild_chat-messages.md. 12..18 are gathering-only — never emit on guild.
|
||||
public enum GuildChatMessageType : int
|
||||
{
|
||||
Normal = 0, Stamp = 1, Deck = 2, Join = 3, Leave = 4, Replay = 5,
|
||||
ChangeLeader = 6, ChangeSubLeader = 7, CreateGuild = 8, Remove = 9,
|
||||
RoomMatch = 10, Description = 11,
|
||||
}
|
||||
12
SVSim.Database/Entities/Guild/GuildInvite.cs
Normal file
12
SVSim.Database/Entities/Guild/GuildInvite.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
namespace SVSim.Database.Entities.Guild;
|
||||
|
||||
public class GuildInvite
|
||||
{
|
||||
public int GuildId { get; set; }
|
||||
public long InviteeViewerId { get; set; }
|
||||
public long InviterViewerId { get; set; }
|
||||
public GuildInviteStatus Status { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public DateTime? RespondedAt { get; set; }
|
||||
public Guild Guild { get; set; } = null!;
|
||||
}
|
||||
11
SVSim.Database/Entities/Guild/GuildJoinRequest.cs
Normal file
11
SVSim.Database/Entities/Guild/GuildJoinRequest.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace SVSim.Database.Entities.Guild;
|
||||
|
||||
public class GuildJoinRequest
|
||||
{
|
||||
public int GuildId { get; set; }
|
||||
public long ViewerId { get; set; }
|
||||
public GuildJoinRequestStatus Status { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public DateTime? RespondedAt { get; set; }
|
||||
public Guild Guild { get; set; } = null!;
|
||||
}
|
||||
10
SVSim.Database/Entities/Guild/GuildMember.cs
Normal file
10
SVSim.Database/Entities/Guild/GuildMember.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace SVSim.Database.Entities.Guild;
|
||||
|
||||
public class GuildMember
|
||||
{
|
||||
public int GuildId { get; set; }
|
||||
public long ViewerId { get; set; }
|
||||
public GuildRole Role { get; set; }
|
||||
public DateTime JoinedAt { get; set; }
|
||||
public Guild Guild { get; set; } = null!;
|
||||
}
|
||||
4998
SVSim.Database/Migrations/20260627150146_AddGuildSchema.Designer.cs
generated
Normal file
4998
SVSim.Database/Migrations/20260627150146_AddGuildSchema.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
207
SVSim.Database/Migrations/20260627150146_AddGuildSchema.cs
Normal file
207
SVSim.Database/Migrations/20260627150146_AddGuildSchema.cs
Normal file
@@ -0,0 +1,207 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace SVSim.Database.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddGuildSchema : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "GuildId",
|
||||
table: "Viewers",
|
||||
type: "integer",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Guilds",
|
||||
columns: table => new
|
||||
{
|
||||
GuildId = table.Column<int>(type: "integer", nullable: false),
|
||||
Name = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false),
|
||||
Description = table.Column<string>(type: "character varying(512)", maxLength: 512, nullable: false),
|
||||
LeaderViewerId = table.Column<long>(type: "bigint", nullable: false),
|
||||
EmblemId = table.Column<long>(type: "bigint", nullable: false),
|
||||
Activity = table.Column<int>(type: "integer", nullable: false),
|
||||
JoinCondition = table.Column<int>(type: "integer", nullable: false),
|
||||
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
|
||||
BreakupAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Guilds", x => x.GuildId);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "GuildChatMessages",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<long>(type: "bigint", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
GuildId = table.Column<int>(type: "integer", nullable: false),
|
||||
MessageId = table.Column<int>(type: "integer", nullable: false),
|
||||
AuthorViewerId = table.Column<long>(type: "bigint", nullable: false),
|
||||
MessageType = table.Column<int>(type: "integer", nullable: false),
|
||||
Body = table.Column<string>(type: "text", nullable: false),
|
||||
DeckPayload = table.Column<string>(type: "jsonb", nullable: true),
|
||||
ReplayPayload = table.Column<string>(type: "jsonb", nullable: true),
|
||||
RoomPayload = table.Column<string>(type: "jsonb", nullable: true),
|
||||
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_GuildChatMessages", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_GuildChatMessages_Guilds_GuildId",
|
||||
column: x => x.GuildId,
|
||||
principalTable: "Guilds",
|
||||
principalColumn: "GuildId",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "GuildInvites",
|
||||
columns: table => new
|
||||
{
|
||||
GuildId = table.Column<int>(type: "integer", nullable: false),
|
||||
InviteeViewerId = table.Column<long>(type: "bigint", nullable: false),
|
||||
InviterViewerId = table.Column<long>(type: "bigint", nullable: false),
|
||||
Status = table.Column<int>(type: "integer", nullable: false),
|
||||
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
|
||||
RespondedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_GuildInvites", x => new { x.GuildId, x.InviteeViewerId });
|
||||
table.ForeignKey(
|
||||
name: "FK_GuildInvites_Guilds_GuildId",
|
||||
column: x => x.GuildId,
|
||||
principalTable: "Guilds",
|
||||
principalColumn: "GuildId",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "GuildJoinRequests",
|
||||
columns: table => new
|
||||
{
|
||||
GuildId = table.Column<int>(type: "integer", nullable: false),
|
||||
ViewerId = table.Column<long>(type: "bigint", nullable: false),
|
||||
Status = table.Column<int>(type: "integer", nullable: false),
|
||||
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
|
||||
RespondedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_GuildJoinRequests", x => new { x.GuildId, x.ViewerId });
|
||||
table.ForeignKey(
|
||||
name: "FK_GuildJoinRequests_Guilds_GuildId",
|
||||
column: x => x.GuildId,
|
||||
principalTable: "Guilds",
|
||||
principalColumn: "GuildId",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "GuildMembers",
|
||||
columns: table => new
|
||||
{
|
||||
GuildId = table.Column<int>(type: "integer", nullable: false),
|
||||
ViewerId = table.Column<long>(type: "bigint", nullable: false),
|
||||
Role = table.Column<int>(type: "integer", nullable: false),
|
||||
JoinedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_GuildMembers", x => new { x.GuildId, x.ViewerId });
|
||||
table.ForeignKey(
|
||||
name: "FK_GuildMembers_Guilds_GuildId",
|
||||
column: x => x.GuildId,
|
||||
principalTable: "Guilds",
|
||||
principalColumn: "GuildId",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Viewers_GuildId",
|
||||
table: "Viewers",
|
||||
column: "GuildId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_GuildChatMessages_GuildId_MessageId",
|
||||
table: "GuildChatMessages",
|
||||
columns: new[] { "GuildId", "MessageId" },
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_GuildInvites_InviteeViewerId_Status",
|
||||
table: "GuildInvites",
|
||||
columns: new[] { "InviteeViewerId", "Status" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_GuildJoinRequests_GuildId_Status",
|
||||
table: "GuildJoinRequests",
|
||||
columns: new[] { "GuildId", "Status" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_GuildJoinRequests_ViewerId_Status",
|
||||
table: "GuildJoinRequests",
|
||||
columns: new[] { "ViewerId", "Status" });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_GuildMembers_ViewerId",
|
||||
table: "GuildMembers",
|
||||
column: "ViewerId",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Guilds_Name",
|
||||
table: "Guilds",
|
||||
column: "Name");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Viewers_Guilds_GuildId",
|
||||
table: "Viewers",
|
||||
column: "GuildId",
|
||||
principalTable: "Guilds",
|
||||
principalColumn: "GuildId",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Viewers_Guilds_GuildId",
|
||||
table: "Viewers");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "GuildChatMessages");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "GuildInvites");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "GuildJoinRequests");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "GuildMembers");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Guilds");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Viewers_GuildId",
|
||||
table: "Viewers");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "GuildId",
|
||||
table: "Viewers");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -85,6 +85,165 @@ namespace SVSim.Database.Migrations
|
||||
b.ToTable("MyPageBackgroundEntryViewer");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SVSim.Database.Entities.Guild.Guild", b =>
|
||||
{
|
||||
b.Property<int>("GuildId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("Activity")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<DateTime?>("BreakupAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasMaxLength(512)
|
||||
.HasColumnType("character varying(512)");
|
||||
|
||||
b.Property<long>("EmblemId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<int>("JoinCondition")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<long>("LeaderViewerId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(64)
|
||||
.HasColumnType("character varying(64)");
|
||||
|
||||
b.HasKey("GuildId");
|
||||
|
||||
b.HasIndex("Name");
|
||||
|
||||
b.ToTable("Guilds");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SVSim.Database.Entities.Guild.GuildChatMessage", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<long>("AuthorViewerId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<string>("Body")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("DeckPayload")
|
||||
.HasColumnType("jsonb");
|
||||
|
||||
b.Property<int>("GuildId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("MessageId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("MessageType")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("ReplayPayload")
|
||||
.HasColumnType("jsonb");
|
||||
|
||||
b.Property<string>("RoomPayload")
|
||||
.HasColumnType("jsonb");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("GuildId", "MessageId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("GuildChatMessages");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SVSim.Database.Entities.Guild.GuildInvite", b =>
|
||||
{
|
||||
b.Property<int>("GuildId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<long>("InviteeViewerId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<long>("InviterViewerId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<DateTime?>("RespondedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<int>("Status")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.HasKey("GuildId", "InviteeViewerId");
|
||||
|
||||
b.HasIndex("InviteeViewerId", "Status");
|
||||
|
||||
b.ToTable("GuildInvites");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SVSim.Database.Entities.Guild.GuildJoinRequest", b =>
|
||||
{
|
||||
b.Property<int>("GuildId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<long>("ViewerId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<DateTime?>("RespondedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<int>("Status")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.HasKey("GuildId", "ViewerId");
|
||||
|
||||
b.HasIndex("GuildId", "Status");
|
||||
|
||||
b.HasIndex("ViewerId", "Status");
|
||||
|
||||
b.ToTable("GuildJoinRequests");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SVSim.Database.Entities.Guild.GuildMember", b =>
|
||||
{
|
||||
b.Property<int>("GuildId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<long>("ViewerId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<DateTime>("JoinedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<int>("Role")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.HasKey("GuildId", "ViewerId");
|
||||
|
||||
b.HasIndex("ViewerId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("GuildMembers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SVSim.Database.Entities.Story.SpecialBattleSetting", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
@@ -2685,6 +2844,9 @@ namespace SVSim.Database.Migrations
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int?>("GuildId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<DateTime>("LastLogin")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
@@ -2712,6 +2874,8 @@ namespace SVSim.Database.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("GuildId");
|
||||
|
||||
b.HasIndex("ShortUdid");
|
||||
|
||||
b.HasIndex("Udid")
|
||||
@@ -3479,6 +3643,50 @@ namespace SVSim.Database.Migrations
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SVSim.Database.Entities.Guild.GuildChatMessage", b =>
|
||||
{
|
||||
b.HasOne("SVSim.Database.Entities.Guild.Guild", "Guild")
|
||||
.WithMany()
|
||||
.HasForeignKey("GuildId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Guild");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SVSim.Database.Entities.Guild.GuildInvite", b =>
|
||||
{
|
||||
b.HasOne("SVSim.Database.Entities.Guild.Guild", "Guild")
|
||||
.WithMany()
|
||||
.HasForeignKey("GuildId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Guild");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SVSim.Database.Entities.Guild.GuildJoinRequest", b =>
|
||||
{
|
||||
b.HasOne("SVSim.Database.Entities.Guild.Guild", "Guild")
|
||||
.WithMany()
|
||||
.HasForeignKey("GuildId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Guild");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SVSim.Database.Entities.Guild.GuildMember", b =>
|
||||
{
|
||||
b.HasOne("SVSim.Database.Entities.Guild.Guild", "Guild")
|
||||
.WithMany("Members")
|
||||
.HasForeignKey("GuildId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Guild");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SVSim.Database.Entities.Story.StoryChapter", b =>
|
||||
{
|
||||
b.HasOne("SVSim.Database.Entities.Story.StorySection", "Section")
|
||||
@@ -4112,6 +4320,11 @@ namespace SVSim.Database.Migrations
|
||||
|
||||
modelBuilder.Entity("SVSim.Database.Models.Viewer", b =>
|
||||
{
|
||||
b.HasOne("SVSim.Database.Entities.Guild.Guild", "Guild")
|
||||
.WithMany()
|
||||
.HasForeignKey("GuildId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
b.OwnsMany("SVSim.Database.Models.MyPageBgRotationEntry", "MyPageBgRotation", b1 =>
|
||||
{
|
||||
b1.Property<long>("ViewerId")
|
||||
@@ -4588,6 +4801,8 @@ namespace SVSim.Database.Migrations
|
||||
|
||||
b.Navigation("GachaPointReceived");
|
||||
|
||||
b.Navigation("Guild");
|
||||
|
||||
b.Navigation("Info")
|
||||
.IsRequired();
|
||||
|
||||
@@ -4719,6 +4934,11 @@ namespace SVSim.Database.Migrations
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SVSim.Database.Entities.Guild.Guild", b =>
|
||||
{
|
||||
b.Navigation("Members");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SVSim.Database.Models.BattlePassSeasonEntry", b =>
|
||||
{
|
||||
b.Navigation("Rewards");
|
||||
|
||||
@@ -105,5 +105,8 @@ public class Viewer : BaseEntity<long>
|
||||
|
||||
public List<SocialAccountConnection> SocialAccountConnections { get; set; } = new List<SocialAccountConnection>();
|
||||
|
||||
public int? GuildId { get; set; }
|
||||
public SVSim.Database.Entities.Guild.Guild? Guild { get; set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using SVSim.Database.Common;
|
||||
using SVSim.Database.Entities.Guild;
|
||||
using SVSim.Database.Entities.Story;
|
||||
using SVSim.Database.Models;
|
||||
using SVSim.Database.Models.Config;
|
||||
@@ -119,6 +120,12 @@ public class SVSimDbContext : DbContext
|
||||
public DbSet<ViewerPlayedTogether> ViewerPlayedTogethers => Set<ViewerPlayedTogether>();
|
||||
public DbSet<ViewerBattleHistory> ViewerBattleHistories => Set<ViewerBattleHistory>();
|
||||
|
||||
public DbSet<Guild> Guilds => Set<Guild>();
|
||||
public DbSet<GuildMember> GuildMembers => Set<GuildMember>();
|
||||
public DbSet<GuildInvite> GuildInvites => Set<GuildInvite>();
|
||||
public DbSet<GuildJoinRequest> GuildJoinRequests => Set<GuildJoinRequest>();
|
||||
public DbSet<GuildChatMessage> GuildChatMessages => Set<GuildChatMessage>();
|
||||
|
||||
#endregion
|
||||
|
||||
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
|
||||
@@ -504,6 +511,59 @@ public class SVSimDbContext : DbContext
|
||||
modelBuilder.Entity<ColosseumWindFallDeck>().HasIndex(d => d.DeckNo).IsUnique();
|
||||
modelBuilder.Entity<ColosseumAvatarDeck>().HasIndex(d => d.DeckNo).IsUnique();
|
||||
|
||||
// --- Guild entities ---
|
||||
|
||||
modelBuilder.Entity<Guild>(e =>
|
||||
{
|
||||
e.HasKey(g => g.GuildId);
|
||||
e.Property(g => g.GuildId).ValueGeneratedNever(); // we pick the random id ourselves
|
||||
e.Property(g => g.Name).HasMaxLength(64);
|
||||
e.Property(g => g.Description).HasMaxLength(512);
|
||||
e.HasIndex(g => g.Name); // name search
|
||||
});
|
||||
|
||||
modelBuilder.Entity<GuildMember>(e =>
|
||||
{
|
||||
e.HasKey(m => new { m.GuildId, m.ViewerId });
|
||||
e.HasOne(m => m.Guild).WithMany(g => g.Members).HasForeignKey(m => m.GuildId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
e.HasIndex(m => m.ViewerId).IsUnique(); // one-guild-per-viewer at DB level
|
||||
});
|
||||
|
||||
modelBuilder.Entity<GuildInvite>(e =>
|
||||
{
|
||||
e.HasKey(i => new { i.GuildId, i.InviteeViewerId });
|
||||
e.HasOne(i => i.Guild).WithMany().HasForeignKey(i => i.GuildId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
e.HasIndex(i => new { i.InviteeViewerId, i.Status }); // "my pending invites"
|
||||
});
|
||||
|
||||
modelBuilder.Entity<GuildJoinRequest>(e =>
|
||||
{
|
||||
e.HasKey(r => new { r.GuildId, r.ViewerId });
|
||||
e.HasOne(r => r.Guild).WithMany().HasForeignKey(r => r.GuildId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
e.HasIndex(r => new { r.ViewerId, r.Status });
|
||||
e.HasIndex(r => new { r.GuildId, r.Status });
|
||||
});
|
||||
|
||||
modelBuilder.Entity<GuildChatMessage>(e =>
|
||||
{
|
||||
e.HasKey(c => c.Id);
|
||||
e.HasOne(c => c.Guild).WithMany().HasForeignKey(c => c.GuildId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
e.HasIndex(c => new { c.GuildId, c.MessageId }).IsUnique();
|
||||
e.Property(c => c.DeckPayload).HasColumnType("jsonb");
|
||||
e.Property(c => c.ReplayPayload).HasColumnType("jsonb");
|
||||
e.Property(c => c.RoomPayload).HasColumnType("jsonb");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Viewer>(e =>
|
||||
{
|
||||
e.HasOne(v => v.Guild).WithMany().HasForeignKey(v => v.GuildId)
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
});
|
||||
|
||||
base.OnModelCreating(modelBuilder);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user