20260705002416_AddConsumableItemsAndProfileCooldown.cs 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. using System;
  2. using Microsoft.EntityFrameworkCore.Migrations;
  3. #nullable disable
  4. namespace Infrastructure.Migrations.AppDb
  5. {
  6. /// <inheritdoc />
  7. public partial class AddConsumableItemsAndProfileCooldown : Migration
  8. {
  9. /// <inheritdoc />
  10. protected override void Up(MigrationBuilder migrationBuilder)
  11. {
  12. migrationBuilder.AlterColumn<int>(
  13. name: "GameID",
  14. table: "Product",
  15. type: "int",
  16. nullable: true,
  17. comment: "게임 ID (선택 — null=플랫폼 직접판매)",
  18. oldClrType: typeof(int),
  19. oldType: "int",
  20. oldComment: "게임 ID (선택 — null=플랫폼 직접판매)");
  21. migrationBuilder.AddColumn<int>(
  22. name: "DurationDays",
  23. table: "Product",
  24. type: "int",
  25. nullable: false,
  26. defaultValue: 0,
  27. comment: "소모품 효과 지속일 (0=즉시소모)");
  28. migrationBuilder.AddColumn<byte>(
  29. name: "ItemKind",
  30. table: "Product",
  31. type: "tinyint",
  32. nullable: true,
  33. comment: "소모품 종류 (null=일반상품, 5~11=소모품)");
  34. migrationBuilder.AddColumn<DateTime>(
  35. name: "LastThumbChangedAt",
  36. table: "Member",
  37. type: "datetime2",
  38. nullable: true);
  39. migrationBuilder.AddColumn<int>(
  40. name: "Account_ChangeThumbDay",
  41. table: "Config",
  42. type: "int",
  43. nullable: true,
  44. comment: "프로필 이미지 갱신 주기(일)");
  45. migrationBuilder.CreateTable(
  46. name: "MemberItem",
  47. columns: table => new
  48. {
  49. ID = table.Column<int>(type: "int", nullable: false, comment: "PK")
  50. .Annotation("SqlServer:Identity", "1, 1"),
  51. MemberID = table.Column<int>(type: "int", nullable: false, comment: "회원 ID"),
  52. ProductID = table.Column<int>(type: "int", nullable: false, comment: "상품 ID"),
  53. OrderItemID = table.Column<int>(type: "int", nullable: false, comment: "발급 근거 주문항목 ID"),
  54. Kind = table.Column<byte>(type: "tinyint", nullable: false, comment: "아이템 종류 (5~11)"),
  55. DurationDays = table.Column<int>(type: "int", nullable: false, defaultValue: 0, comment: "효과 지속일 (0=즉시소모)"),
  56. AcquiredAt = table.Column<DateTime>(type: "datetime2", nullable: false, comment: "획득 일시"),
  57. UsedAt = table.Column<DateTime>(type: "datetime2", nullable: true, comment: "소모/활성 일시 (null=미사용)"),
  58. RevokedAt = table.Column<DateTime>(type: "datetime2", nullable: true, comment: "회수 일시 (환불)"),
  59. RowVersion = table.Column<byte[]>(type: "rowversion", rowVersion: true, nullable: false)
  60. },
  61. constraints: table =>
  62. {
  63. table.PrimaryKey("PK_MemberItem", x => x.ID);
  64. table.ForeignKey(
  65. name: "FK_MemberItem_Member_MemberID",
  66. column: x => x.MemberID,
  67. principalTable: "Member",
  68. principalColumn: "ID",
  69. onDelete: ReferentialAction.Cascade);
  70. table.ForeignKey(
  71. name: "FK_MemberItem_Product_ProductID",
  72. column: x => x.ProductID,
  73. principalTable: "Product",
  74. principalColumn: "ID",
  75. onDelete: ReferentialAction.Restrict);
  76. },
  77. comment: "계정 귀속 소모품 아이템");
  78. migrationBuilder.CreateTable(
  79. name: "MemberItemUsageLog",
  80. columns: table => new
  81. {
  82. ID = table.Column<int>(type: "int", nullable: false, comment: "PK")
  83. .Annotation("SqlServer:Identity", "1, 1"),
  84. MemberID = table.Column<int>(type: "int", nullable: false, comment: "회원 ID"),
  85. MemberItemID = table.Column<int>(type: "int", nullable: false, comment: "MemberItem ID"),
  86. ProductID = table.Column<int>(type: "int", nullable: false, comment: "상품 ID"),
  87. Kind = table.Column<byte>(type: "tinyint", nullable: false, comment: "아이템 종류"),
  88. Action = table.Column<byte>(type: "tinyint", nullable: false, comment: "액션 (1=Used, 2=Revoked)"),
  89. Detail = table.Column<string>(type: "nvarchar(300)", maxLength: 300, nullable: true, comment: "결과 요약"),
  90. CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false, comment: "등록 일시")
  91. },
  92. constraints: table =>
  93. {
  94. table.PrimaryKey("PK_MemberItemUsageLog", x => x.ID);
  95. },
  96. comment: "소모품 아이템 사용/회수 로그");
  97. migrationBuilder.CreateTable(
  98. name: "MemberThumbChangeLog",
  99. columns: table => new
  100. {
  101. ID = table.Column<int>(type: "int", nullable: false, comment: "PK")
  102. .Annotation("SqlServer:Identity", "1, 1"),
  103. MemberID = table.Column<int>(type: "int", nullable: false, comment: "회원 ID"),
  104. BeforeThumb = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: true, comment: "이전 이미지"),
  105. AfterThumb = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: true, comment: "바꾼 이미지"),
  106. Referer = table.Column<string>(type: "nvarchar(max)", nullable: true, comment: "이전 페이지 주소"),
  107. IpAddress = table.Column<string>(type: "nvarchar(45)", maxLength: 45, nullable: true, comment: "IP Address (IPv6 호환)"),
  108. UserAgent = table.Column<string>(type: "nvarchar(512)", maxLength: 512, nullable: true, comment: "User Agent"),
  109. CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false, comment: "등록 일시")
  110. },
  111. constraints: table =>
  112. {
  113. table.PrimaryKey("PK_MemberThumbChangeLog", x => x.ID);
  114. table.ForeignKey(
  115. name: "FK_MemberThumbChangeLog_Member_MemberID",
  116. column: x => x.MemberID,
  117. principalTable: "Member",
  118. principalColumn: "ID",
  119. onDelete: ReferentialAction.Cascade);
  120. },
  121. comment: "프로필 이미지 변경 내역");
  122. migrationBuilder.CreateIndex(
  123. name: "IX_Product_ItemKind_IsActive",
  124. table: "Product",
  125. columns: new[] { "ItemKind", "IsActive" });
  126. migrationBuilder.CreateIndex(
  127. name: "IX_MemberItem_MemberID_Kind_UsedAt",
  128. table: "MemberItem",
  129. columns: new[] { "MemberID", "Kind", "UsedAt" });
  130. migrationBuilder.CreateIndex(
  131. name: "IX_MemberItem_OrderItemID",
  132. table: "MemberItem",
  133. column: "OrderItemID");
  134. migrationBuilder.CreateIndex(
  135. name: "IX_MemberItem_ProductID",
  136. table: "MemberItem",
  137. column: "ProductID");
  138. migrationBuilder.CreateIndex(
  139. name: "IX_MemberItemUsageLog_MemberID_CreatedAt",
  140. table: "MemberItemUsageLog",
  141. columns: new[] { "MemberID", "CreatedAt" });
  142. migrationBuilder.CreateIndex(
  143. name: "IX_MemberThumbChangeLog_MemberID",
  144. table: "MemberThumbChangeLog",
  145. column: "MemberID");
  146. // 기존 Config 싱글턴에 프로필(닉네임·한마디·이미지) 90일 쿨다운 활성화 — Wave 3 P3 결정 #3.
  147. // Name/Intro 는 미설정(NULL)일 때만 90 으로, Thumb 는 신규 컬럼이라 전부 90 으로 채운다.
  148. migrationBuilder.Sql(@"
  149. UPDATE [Config]
  150. SET [Account_ChangeNameDay] = COALESCE([Account_ChangeNameDay], 90),
  151. [Account_ChangeIntroDay] = COALESCE([Account_ChangeIntroDay], 90),
  152. [Account_ChangeThumbDay] = 90
  153. WHERE [Account_ChangeThumbDay] IS NULL;");
  154. }
  155. /// <inheritdoc />
  156. protected override void Down(MigrationBuilder migrationBuilder)
  157. {
  158. migrationBuilder.DropTable(
  159. name: "MemberItem");
  160. migrationBuilder.DropTable(
  161. name: "MemberItemUsageLog");
  162. migrationBuilder.DropTable(
  163. name: "MemberThumbChangeLog");
  164. migrationBuilder.DropIndex(
  165. name: "IX_Product_ItemKind_IsActive",
  166. table: "Product");
  167. migrationBuilder.DropColumn(
  168. name: "DurationDays",
  169. table: "Product");
  170. migrationBuilder.DropColumn(
  171. name: "ItemKind",
  172. table: "Product");
  173. migrationBuilder.DropColumn(
  174. name: "LastThumbChangedAt",
  175. table: "Member");
  176. migrationBuilder.DropColumn(
  177. name: "Account_ChangeThumbDay",
  178. table: "Config");
  179. migrationBuilder.AlterColumn<int>(
  180. name: "GameID",
  181. table: "Product",
  182. type: "int",
  183. nullable: false,
  184. defaultValue: 0,
  185. comment: "게임 ID (필수)",
  186. oldClrType: typeof(int),
  187. oldType: "int",
  188. oldNullable: true,
  189. oldComment: "게임 ID (선택 — null=플랫폼 직접판매)");
  190. }
  191. }
  192. }