20260417000739_AddRankingAndBroadcastEntities.cs 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. using System;
  2. using Microsoft.EntityFrameworkCore.Migrations;
  3. #nullable disable
  4. namespace Infrastructure.Migrations.AppDb;
  5. /// <inheritdoc />
  6. public partial class AddRankingAndBroadcastEntities : Migration
  7. {
  8. /// <inheritdoc />
  9. protected override void Up(MigrationBuilder migrationBuilder)
  10. {
  11. migrationBuilder.CreateTable(
  12. name: "BroadcastSession",
  13. columns: table => new
  14. {
  15. ID = table.Column<int>(type: "int", nullable: false)
  16. .Annotation("SqlServer:Identity", "1, 1"),
  17. ChannelID = table.Column<int>(type: "int", nullable: false, comment: "채널 ID"),
  18. Platform = table.Column<int>(type: "int", nullable: false, comment: "플랫폼 (YouTube=1)"),
  19. VideoID = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: false, comment: "플랫폼 비디오 ID"),
  20. Title = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: true, comment: "방송 제목"),
  21. StartAt = table.Column<DateTime>(type: "datetime2", nullable: true, comment: "방송 시작 시각"),
  22. EndAt = table.Column<DateTime>(type: "datetime2", nullable: true, comment: "방송 종료 시각"),
  23. DurationSec = table.Column<int>(type: "int", nullable: false, comment: "방송 시간 (초)"),
  24. FinalViews = table.Column<long>(type: "bigint", nullable: false, comment: "최종 조회수"),
  25. FinalLikes = table.Column<long>(type: "bigint", nullable: false, comment: "최종 좋아요"),
  26. IsFinalized = table.Column<bool>(type: "bit", nullable: false, comment: "최종 확정 여부 (End + 24h 경과)"),
  27. UpdatedAt = table.Column<DateTime>(type: "datetime2", nullable: true, comment: "수정 일시"),
  28. CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false, comment: "생성 일시")
  29. },
  30. constraints: table =>
  31. {
  32. table.PrimaryKey("PK_BroadcastSession", x => x.ID);
  33. table.ForeignKey(
  34. name: "FK_BroadcastSession_Channel_ChannelID",
  35. column: x => x.ChannelID,
  36. principalTable: "Channel",
  37. principalColumn: "ID",
  38. onDelete: ReferentialAction.Cascade);
  39. },
  40. comment: "방송 세션 (라이브 1회 단위)");
  41. migrationBuilder.CreateTable(
  42. name: "ChannelBroadcastStats",
  43. columns: table => new
  44. {
  45. ChannelID = table.Column<int>(type: "int", nullable: false, comment: "채널 ID"),
  46. TotalDurationSec = table.Column<long>(type: "bigint", nullable: false, comment: "누적 방송 시간 (초)"),
  47. CumulativeViews = table.Column<long>(type: "bigint", nullable: false, comment: "누적 조회수"),
  48. TotalLikes = table.Column<long>(type: "bigint", nullable: false, comment: "누적 좋아요"),
  49. SessionCount = table.Column<int>(type: "int", nullable: false, comment: "방송 횟수"),
  50. LastBroadcastAt = table.Column<DateTime>(type: "datetime2", nullable: true, comment: "마지막 방송 일시"),
  51. LastAggregatedAt = table.Column<DateTime>(type: "datetime2", nullable: true, comment: "마지막 집계 일시"),
  52. CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false, comment: "생성 일시")
  53. },
  54. constraints: table =>
  55. {
  56. table.PrimaryKey("PK_ChannelBroadcastStats", x => x.ChannelID);
  57. table.ForeignKey(
  58. name: "FK_ChannelBroadcastStats_Channel_ChannelID",
  59. column: x => x.ChannelID,
  60. principalTable: "Channel",
  61. principalColumn: "ID",
  62. onDelete: ReferentialAction.Cascade);
  63. },
  64. comment: "채널별 누적 방송 지표");
  65. migrationBuilder.CreateTable(
  66. name: "RankingSnapshot",
  67. columns: table => new
  68. {
  69. ID = table.Column<int>(type: "int", nullable: false)
  70. .Annotation("SqlServer:Identity", "1, 1"),
  71. Type = table.Column<int>(type: "int", nullable: false, comment: "랭킹 종류 (1=종합, 2=크리에이터, 3=후원자)"),
  72. Period = table.Column<int>(type: "int", nullable: false, comment: "기간 (1=오늘, 2=어제, 3=이번주, 4=이번달, 5=지난달, 6=전체)"),
  73. PeriodStart = table.Column<DateTime>(type: "datetime2", nullable: false, comment: "기간 시작"),
  74. PeriodEnd = table.Column<DateTime>(type: "datetime2", nullable: false, comment: "기간 종료"),
  75. Category = table.Column<string>(type: "nvarchar(30)", maxLength: 30, nullable: true, comment: "카테고리 (전체/게임/버츄얼/토크/음악/먹방)"),
  76. MemberID = table.Column<int>(type: "int", nullable: false, comment: "회원 ID"),
  77. Rank = table.Column<int>(type: "int", nullable: false, comment: "순위"),
  78. PreviousRank = table.Column<int>(type: "int", nullable: true, comment: "전일 순위"),
  79. Score = table.Column<long>(type: "bigint", nullable: false, comment: "종합 점수"),
  80. MoneyAmount = table.Column<long>(type: "bigint", nullable: false, comment: "수령/후원 금액"),
  81. DonorCount = table.Column<int>(type: "int", nullable: false, comment: "후원자 수"),
  82. BroadcastSec = table.Column<long>(type: "bigint", nullable: false, comment: "방송 시간 (초)"),
  83. ViewCount = table.Column<long>(type: "bigint", nullable: false, comment: "조회수"),
  84. LikeCount = table.Column<long>(type: "bigint", nullable: false, comment: "좋아요"),
  85. SnapshotAt = table.Column<DateTime>(type: "datetime2", nullable: false, comment: "스냅샷 일시")
  86. },
  87. constraints: table =>
  88. {
  89. table.PrimaryKey("PK_RankingSnapshot", x => x.ID);
  90. table.ForeignKey(
  91. name: "FK_RankingSnapshot_Member_MemberID",
  92. column: x => x.MemberID,
  93. principalTable: "Member",
  94. principalColumn: "ID");
  95. },
  96. comment: "랭킹 스냅샷 (일 1회 집계)");
  97. migrationBuilder.CreateIndex(
  98. name: "IX_BroadcastSession_ChannelID_EndAt",
  99. table: "BroadcastSession",
  100. columns: new[] { "ChannelID", "EndAt" },
  101. descending: new[] { false, true });
  102. migrationBuilder.CreateIndex(
  103. name: "IX_BroadcastSession_IsFinalized",
  104. table: "BroadcastSession",
  105. column: "IsFinalized");
  106. migrationBuilder.CreateIndex(
  107. name: "IX_BroadcastSession_Platform_VideoID",
  108. table: "BroadcastSession",
  109. columns: new[] { "Platform", "VideoID" },
  110. unique: true);
  111. migrationBuilder.CreateIndex(
  112. name: "IX_RankingSnapshot_MemberID",
  113. table: "RankingSnapshot",
  114. column: "MemberID");
  115. migrationBuilder.CreateIndex(
  116. name: "IX_RankingSnapshot_SnapshotAt",
  117. table: "RankingSnapshot",
  118. column: "SnapshotAt",
  119. descending: new bool[0]);
  120. migrationBuilder.CreateIndex(
  121. name: "IX_RankingSnapshot_Type_Period_Category_MemberID",
  122. table: "RankingSnapshot",
  123. columns: new[] { "Type", "Period", "Category", "MemberID" },
  124. unique: true,
  125. filter: "[Category] IS NOT NULL");
  126. migrationBuilder.CreateIndex(
  127. name: "IX_RankingSnapshot_Type_Period_Category_Rank",
  128. table: "RankingSnapshot",
  129. columns: new[] { "Type", "Period", "Category", "Rank" });
  130. }
  131. /// <inheritdoc />
  132. protected override void Down(MigrationBuilder migrationBuilder)
  133. {
  134. migrationBuilder.DropTable(
  135. name: "BroadcastSession");
  136. migrationBuilder.DropTable(
  137. name: "ChannelBroadcastStats");
  138. migrationBuilder.DropTable(
  139. name: "RankingSnapshot");
  140. }
  141. }