From 8b6fd84b98ccbe42ff3523089b9ba6d40b4e1d3d Mon Sep 17 00:00:00 2001 From: SEAN Date: Mon, 9 Feb 2026 13:31:50 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20Domain=20Enum=20=EB=B0=8F=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=20=EC=BD=94=EB=93=9C=20=EC=83=81=EC=88=98=20=EC=A0=95?= =?UTF-8?q?=EC=9D=98=20(#10)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 12개 Enum 추가 (Platform, ServiceStatus, SubTier, AdminRole, DeviceStatus, MessageStatus, PushResult, PaymentStatus, TargetType, LinkType, WebhookEvent, WebhookStatus) - ErrorCodes 상수 클래스 추가 (Error_Codes.md 기반 3자리 코드) - Entity byte 필드를 Enum 타입으로 변경 (Service, Admin, Device, PushSendLog, WebhookLog, Payment) - WebhookLog.EventType 컬럼 타입 변경 (varchar→tinyint) 마이그레이션 적용 --- SPMS.Domain/Common/ErrorCodes.cs | 33 + SPMS.Domain/Entities/Admin.cs | 4 +- SPMS.Domain/Entities/Device.cs | 4 +- SPMS.Domain/Entities/Payment.cs | 8 +- SPMS.Domain/Entities/PushSendLog.cs | 4 +- SPMS.Domain/Entities/Service.cs | 6 +- SPMS.Domain/Entities/WebhookLog.cs | 6 +- SPMS.Domain/Enums/AdminRole.cs | 11 + SPMS.Domain/Enums/DeviceStatus.cs | 11 + SPMS.Domain/Enums/LinkType.cs | 11 + SPMS.Domain/Enums/MessageStatus.cs | 14 + SPMS.Domain/Enums/PaymentStatus.cs | 11 + SPMS.Domain/Enums/Platform.cs | 11 + SPMS.Domain/Enums/PushResult.cs | 10 + SPMS.Domain/Enums/ServiceStatus.cs | 10 + SPMS.Domain/Enums/SubTier.cs | 11 + SPMS.Domain/Enums/TargetType.cs | 12 + SPMS.Domain/Enums/WebhookEvent.cs | 11 + SPMS.Domain/Enums/WebhookStatus.cs | 10 + ...0260209042244_ApplyDomainEnums.Designer.cs | 837 ++++++++++++++++++ .../20260209042244_ApplyDomainEnums.cs | 38 + .../Migrations/AppDbContextModelSnapshot.cs | 6 +- .../Configurations/WebhookLogConfiguration.cs | 2 +- 23 files changed, 1066 insertions(+), 15 deletions(-) create mode 100644 SPMS.Domain/Common/ErrorCodes.cs create mode 100644 SPMS.Domain/Enums/AdminRole.cs create mode 100644 SPMS.Domain/Enums/DeviceStatus.cs create mode 100644 SPMS.Domain/Enums/LinkType.cs create mode 100644 SPMS.Domain/Enums/MessageStatus.cs create mode 100644 SPMS.Domain/Enums/PaymentStatus.cs create mode 100644 SPMS.Domain/Enums/Platform.cs create mode 100644 SPMS.Domain/Enums/PushResult.cs create mode 100644 SPMS.Domain/Enums/ServiceStatus.cs create mode 100644 SPMS.Domain/Enums/SubTier.cs create mode 100644 SPMS.Domain/Enums/TargetType.cs create mode 100644 SPMS.Domain/Enums/WebhookEvent.cs create mode 100644 SPMS.Domain/Enums/WebhookStatus.cs create mode 100644 SPMS.Infrastructure/Migrations/20260209042244_ApplyDomainEnums.Designer.cs create mode 100644 SPMS.Infrastructure/Migrations/20260209042244_ApplyDomainEnums.cs diff --git a/SPMS.Domain/Common/ErrorCodes.cs b/SPMS.Domain/Common/ErrorCodes.cs new file mode 100644 index 0000000..0194968 --- /dev/null +++ b/SPMS.Domain/Common/ErrorCodes.cs @@ -0,0 +1,33 @@ +namespace SPMS.Domain.Common; + +/// +/// SPMS 에러 코드 상수 +/// 코드 체계: [상태(0=성공,1=실패)][도메인(0~8)][순번] +/// +public static class ErrorCodes +{ + // === 성공 === + public const string Success = "000"; + + // === 공통 (0) === + public const string BadRequest = "101"; + public const string Unauthorized = "102"; + public const string NotFound = "103"; + public const string InternalError = "104"; + public const string NoChange = "105"; + public const string LimitExceeded = "106"; + public const string Conflict = "107"; + + // === Auth (1) === + public const string VerificationCodeError = "111"; + public const string LoginFailed = "112"; + public const string LoginAttemptExceeded = "113"; + + // === Account (2) === + public const string PasswordValidationFailed = "121"; + public const string ResetTokenError = "122"; + + // === Push (6) === + public const string PushSendFailed = "161"; + public const string PushStateChangeNotAllowed = "162"; +} diff --git a/SPMS.Domain/Entities/Admin.cs b/SPMS.Domain/Entities/Admin.cs index 6ebbe9e..351243b 100644 --- a/SPMS.Domain/Entities/Admin.cs +++ b/SPMS.Domain/Entities/Admin.cs @@ -1,3 +1,5 @@ +using SPMS.Domain.Enums; + namespace SPMS.Domain.Entities; public class Admin : BaseEntity @@ -7,7 +9,7 @@ public class Admin : BaseEntity public string Password { get; set; } = string.Empty; public string Phone { get; set; } = string.Empty; public string Name { get; set; } = string.Empty; - public byte Role { get; set; } + public AdminRole Role { get; set; } public bool EmailVerified { get; set; } public DateTime? EmailVerifiedAt { get; set; } public DateTime CreatedAt { get; set; } diff --git a/SPMS.Domain/Entities/Device.cs b/SPMS.Domain/Entities/Device.cs index 2955de0..eb8aa3c 100644 --- a/SPMS.Domain/Entities/Device.cs +++ b/SPMS.Domain/Entities/Device.cs @@ -1,10 +1,12 @@ +using SPMS.Domain.Enums; + namespace SPMS.Domain.Entities; public class Device : BaseEntity { public long ServiceId { get; set; } public string DeviceToken { get; set; } = string.Empty; - public byte Platform { get; set; } + public Platform Platform { get; set; } public string? AppVersion { get; set; } public string? OsVersion { get; set; } public string? DeviceModel { get; set; } diff --git a/SPMS.Domain/Entities/Payment.cs b/SPMS.Domain/Entities/Payment.cs index 5d0497c..ab3939e 100644 --- a/SPMS.Domain/Entities/Payment.cs +++ b/SPMS.Domain/Entities/Payment.cs @@ -1,3 +1,5 @@ +using SPMS.Domain.Enums; + namespace SPMS.Domain.Entities; public class Payment : BaseEntity @@ -8,9 +10,9 @@ public class Payment : BaseEntity public string Currency { get; set; } = string.Empty; public string? PaymentMethod { get; set; } public string? PaymentKey { get; set; } - public byte Status { get; set; } - public byte? TierBefore { get; set; } - public byte TierAfter { get; set; } + public PaymentStatus Status { get; set; } + public SubTier? TierBefore { get; set; } + public SubTier TierAfter { get; set; } public DateTime PaidAt { get; set; } public DateTime CreatedAt { get; set; } diff --git a/SPMS.Domain/Entities/PushSendLog.cs b/SPMS.Domain/Entities/PushSendLog.cs index d96554a..d647961 100644 --- a/SPMS.Domain/Entities/PushSendLog.cs +++ b/SPMS.Domain/Entities/PushSendLog.cs @@ -1,3 +1,5 @@ +using SPMS.Domain.Enums; + namespace SPMS.Domain.Entities; public class PushSendLog : BaseEntity @@ -5,7 +7,7 @@ public class PushSendLog : BaseEntity public long ServiceId { get; set; } public long MessageId { get; set; } public long DeviceId { get; set; } - public byte Status { get; set; } + public PushResult Status { get; set; } public string? FailReason { get; set; } public DateTime SentAt { get; set; } diff --git a/SPMS.Domain/Entities/Service.cs b/SPMS.Domain/Entities/Service.cs index 8366f9d..73be73b 100644 --- a/SPMS.Domain/Entities/Service.cs +++ b/SPMS.Domain/Entities/Service.cs @@ -1,3 +1,5 @@ +using SPMS.Domain.Enums; + namespace SPMS.Domain.Entities; public class Service : BaseEntity @@ -14,9 +16,9 @@ public class Service : BaseEntity public string? FcmCredentials { get; set; } public string? WebhookUrl { get; set; } public string? Tags { get; set; } - public byte SubTier { get; set; } + public SubTier SubTier { get; set; } public DateTime? SubStartedAt { get; set; } - public byte Status { get; set; } + public ServiceStatus Status { get; set; } public DateTime CreatedAt { get; set; } public long CreatedBy { get; set; } public DateTime? UpdatedAt { get; set; } diff --git a/SPMS.Domain/Entities/WebhookLog.cs b/SPMS.Domain/Entities/WebhookLog.cs index ed16fa7..f2fcaa6 100644 --- a/SPMS.Domain/Entities/WebhookLog.cs +++ b/SPMS.Domain/Entities/WebhookLog.cs @@ -1,12 +1,14 @@ +using SPMS.Domain.Enums; + namespace SPMS.Domain.Entities; public class WebhookLog : BaseEntity { public long ServiceId { get; set; } public string WebhookUrl { get; set; } = string.Empty; - public string EventType { get; set; } = string.Empty; + public WebhookEvent EventType { get; set; } public string Payload { get; set; } = string.Empty; - public byte Status { get; set; } + public WebhookStatus Status { get; set; } public int? ResponseCode { get; set; } public string? ResponseBody { get; set; } public DateTime SentAt { get; set; } diff --git a/SPMS.Domain/Enums/AdminRole.cs b/SPMS.Domain/Enums/AdminRole.cs new file mode 100644 index 0000000..81330e9 --- /dev/null +++ b/SPMS.Domain/Enums/AdminRole.cs @@ -0,0 +1,11 @@ +namespace SPMS.Domain.Enums; + +/// +/// 관리자 권한 (Admin.role) +/// +public enum AdminRole : byte +{ + Super = 0, + Manager = 1, + User = 2 +} diff --git a/SPMS.Domain/Enums/DeviceStatus.cs b/SPMS.Domain/Enums/DeviceStatus.cs new file mode 100644 index 0000000..8b25766 --- /dev/null +++ b/SPMS.Domain/Enums/DeviceStatus.cs @@ -0,0 +1,11 @@ +namespace SPMS.Domain.Enums; + +/// +/// 디바이스 상태 +/// +public enum DeviceStatus : byte +{ + Active = 0, + Inactive = 1, + Blocked = 2 +} diff --git a/SPMS.Domain/Enums/LinkType.cs b/SPMS.Domain/Enums/LinkType.cs new file mode 100644 index 0000000..606fdea --- /dev/null +++ b/SPMS.Domain/Enums/LinkType.cs @@ -0,0 +1,11 @@ +namespace SPMS.Domain.Enums; + +/// +/// 링크 유형 +/// +public enum LinkType : byte +{ + App = 0, + Web = 1, + DeepLink = 2 +} diff --git a/SPMS.Domain/Enums/MessageStatus.cs b/SPMS.Domain/Enums/MessageStatus.cs new file mode 100644 index 0000000..98a9675 --- /dev/null +++ b/SPMS.Domain/Enums/MessageStatus.cs @@ -0,0 +1,14 @@ +namespace SPMS.Domain.Enums; + +/// +/// 메시지 발송 상태 +/// +public enum MessageStatus : byte +{ + Draft = 0, + Pending = 1, + Sending = 2, + Sent = 3, + Failed = 4, + Cancelled = 5 +} diff --git a/SPMS.Domain/Enums/PaymentStatus.cs b/SPMS.Domain/Enums/PaymentStatus.cs new file mode 100644 index 0000000..3fdc096 --- /dev/null +++ b/SPMS.Domain/Enums/PaymentStatus.cs @@ -0,0 +1,11 @@ +namespace SPMS.Domain.Enums; + +/// +/// 결제 상태 (Payment.status) +/// +public enum PaymentStatus : byte +{ + Completed = 0, + Cancelled = 1, + Refunded = 2 +} diff --git a/SPMS.Domain/Enums/Platform.cs b/SPMS.Domain/Enums/Platform.cs new file mode 100644 index 0000000..b6f3673 --- /dev/null +++ b/SPMS.Domain/Enums/Platform.cs @@ -0,0 +1,11 @@ +namespace SPMS.Domain.Enums; + +/// +/// 디바이스 플랫폼 (Device.platform) +/// +public enum Platform : byte +{ + iOS = 0, + Android = 1, + Web = 2 +} diff --git a/SPMS.Domain/Enums/PushResult.cs b/SPMS.Domain/Enums/PushResult.cs new file mode 100644 index 0000000..2b4a121 --- /dev/null +++ b/SPMS.Domain/Enums/PushResult.cs @@ -0,0 +1,10 @@ +namespace SPMS.Domain.Enums; + +/// +/// 푸시 발송 결과 (PushSendLog.status) +/// +public enum PushResult : byte +{ + Success = 0, + Failed = 1 +} diff --git a/SPMS.Domain/Enums/ServiceStatus.cs b/SPMS.Domain/Enums/ServiceStatus.cs new file mode 100644 index 0000000..e8c4c09 --- /dev/null +++ b/SPMS.Domain/Enums/ServiceStatus.cs @@ -0,0 +1,10 @@ +namespace SPMS.Domain.Enums; + +/// +/// 서비스 상태 (Service.status) +/// +public enum ServiceStatus : byte +{ + Active = 0, + Suspended = 1 +} diff --git a/SPMS.Domain/Enums/SubTier.cs b/SPMS.Domain/Enums/SubTier.cs new file mode 100644 index 0000000..cb2d18f --- /dev/null +++ b/SPMS.Domain/Enums/SubTier.cs @@ -0,0 +1,11 @@ +namespace SPMS.Domain.Enums; + +/// +/// 구독 티어 (Service.sub_tier) +/// +public enum SubTier : byte +{ + Free = 0, + Basic = 1, + Pro = 2 +} diff --git a/SPMS.Domain/Enums/TargetType.cs b/SPMS.Domain/Enums/TargetType.cs new file mode 100644 index 0000000..f722c5d --- /dev/null +++ b/SPMS.Domain/Enums/TargetType.cs @@ -0,0 +1,12 @@ +namespace SPMS.Domain.Enums; + +/// +/// 발송 대상 유형 +/// +public enum TargetType : byte +{ + All = 0, + Filter = 1, + CsvFile = 2, + UserList = 3 +} diff --git a/SPMS.Domain/Enums/WebhookEvent.cs b/SPMS.Domain/Enums/WebhookEvent.cs new file mode 100644 index 0000000..d60b0dc --- /dev/null +++ b/SPMS.Domain/Enums/WebhookEvent.cs @@ -0,0 +1,11 @@ +namespace SPMS.Domain.Enums; + +/// +/// 웹훅 이벤트 유형 (WebhookLog.event_type) +/// +public enum WebhookEvent : byte +{ + PushSent = 0, + PushFailed = 1, + PushClicked = 2 +} diff --git a/SPMS.Domain/Enums/WebhookStatus.cs b/SPMS.Domain/Enums/WebhookStatus.cs new file mode 100644 index 0000000..b2f92f5 --- /dev/null +++ b/SPMS.Domain/Enums/WebhookStatus.cs @@ -0,0 +1,10 @@ +namespace SPMS.Domain.Enums; + +/// +/// 웹훅 발송 결과 (WebhookLog.status) +/// +public enum WebhookStatus : byte +{ + Success = 0, + Failed = 1 +} diff --git a/SPMS.Infrastructure/Migrations/20260209042244_ApplyDomainEnums.Designer.cs b/SPMS.Infrastructure/Migrations/20260209042244_ApplyDomainEnums.Designer.cs new file mode 100644 index 0000000..4b8c815 --- /dev/null +++ b/SPMS.Infrastructure/Migrations/20260209042244_ApplyDomainEnums.Designer.cs @@ -0,0 +1,837 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using SPMS.Infrastructure; + +#nullable disable + +namespace SPMS.Infrastructure.Migrations +{ + [DbContext(typeof(AppDbContext))] + [Migration("20260209042244_ApplyDomainEnums")] + partial class ApplyDomainEnums + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.11") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); + + modelBuilder.Entity("SPMS.Domain.Entities.Admin", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("AdminCode") + .IsRequired() + .HasMaxLength(8) + .HasColumnType("varchar(8)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DeletedAt") + .HasColumnType("datetime(6)"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("EmailVerified") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("EmailVerifiedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("LastLoginAt") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("Phone") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("varchar(20)"); + + b.Property("Role") + .HasColumnType("tinyint"); + + b.HasKey("Id"); + + b.HasIndex("AdminCode") + .IsUnique(); + + b.HasIndex("Email") + .IsUnique(); + + b.ToTable("Admin", (string)null); + }); + + modelBuilder.Entity("SPMS.Domain.Entities.DailyStat", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("FailCnt") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(0); + + b.Property("OpenCnt") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(0); + + b.Property("SentCnt") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(0); + + b.Property("ServiceId") + .HasColumnType("bigint"); + + b.Property("StatDate") + .HasColumnType("date"); + + b.Property("SuccessCnt") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(0); + + b.HasKey("Id"); + + b.HasIndex("ServiceId", "StatDate") + .IsUnique(); + + b.ToTable("DailyStat", (string)null); + }); + + modelBuilder.Entity("SPMS.Domain.Entities.Device", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("AgreeUpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("AppVersion") + .HasMaxLength(20) + .HasColumnType("varchar(20)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DeviceModel") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("DeviceToken") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("varchar(255)"); + + b.Property("IsActive") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(true); + + b.Property("MarketingAgreed") + .HasColumnType("tinyint(1)"); + + b.Property("MktAgreeUpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("OsVersion") + .HasMaxLength(20) + .HasColumnType("varchar(20)"); + + b.Property("Platform") + .HasColumnType("tinyint"); + + b.Property("PushAgreed") + .HasColumnType("tinyint(1)"); + + b.Property("ServiceId") + .HasColumnType("bigint"); + + b.Property("Tags") + .HasColumnType("json"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("ServiceId", "DeviceToken"); + + b.ToTable("Device", (string)null); + }); + + modelBuilder.Entity("SPMS.Domain.Entities.FileEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedBy") + .HasColumnType("bigint"); + + b.Property("FileName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("FilePath") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("FileSize") + .HasColumnType("bigint"); + + b.Property("FileType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("varchar(20)"); + + b.Property("MimeType") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("ServiceId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("ServiceId"); + + b.ToTable("File", (string)null); + }); + + modelBuilder.Entity("SPMS.Domain.Entities.Message", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Body") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedBy") + .HasColumnType("bigint"); + + b.Property("CustomData") + .HasColumnType("json"); + + b.Property("DeletedAt") + .HasColumnType("datetime(6)"); + + b.Property("ImageUrl") + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("LinkUrl") + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("MessageCode") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("varchar(10)"); + + b.Property("ServiceId") + .HasColumnType("bigint"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("MessageCode") + .IsUnique(); + + b.HasIndex("ServiceId"); + + b.ToTable("Message", (string)null); + }); + + modelBuilder.Entity("SPMS.Domain.Entities.Payment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("AdminId") + .HasColumnType("bigint"); + + b.Property("Amount") + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Currency") + .IsRequired() + .HasMaxLength(10) + .HasColumnType("varchar(10)"); + + b.Property("PaidAt") + .HasColumnType("datetime(6)"); + + b.Property("PaymentKey") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("PaymentMethod") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("ServiceId") + .HasColumnType("bigint"); + + b.Property("Status") + .HasColumnType("tinyint"); + + b.Property("TierAfter") + .HasColumnType("tinyint"); + + b.Property("TierBefore") + .HasColumnType("tinyint"); + + b.HasKey("Id"); + + b.HasIndex("AdminId"); + + b.HasIndex("ServiceId"); + + b.ToTable("Payment", (string)null); + }); + + modelBuilder.Entity("SPMS.Domain.Entities.PushOpenLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("DeviceId") + .HasColumnType("bigint"); + + b.Property("MessageId") + .HasColumnType("bigint"); + + b.Property("OpenedAt") + .HasColumnType("datetime(6)"); + + b.Property("ServiceId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("DeviceId"); + + b.HasIndex("MessageId"); + + b.HasIndex("ServiceId", "OpenedAt"); + + b.ToTable("PushOpenLog", (string)null); + }); + + modelBuilder.Entity("SPMS.Domain.Entities.PushSendLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("DeviceId") + .HasColumnType("bigint"); + + b.Property("FailReason") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("MessageId") + .HasColumnType("bigint"); + + b.Property("SentAt") + .HasColumnType("datetime(6)"); + + b.Property("ServiceId") + .HasColumnType("bigint"); + + b.Property("Status") + .HasColumnType("tinyint"); + + b.HasKey("Id"); + + b.HasIndex("DeviceId"); + + b.HasIndex("MessageId"); + + b.HasIndex("ServiceId", "SentAt"); + + b.ToTable("PushSendLog", (string)null); + }); + + modelBuilder.Entity("SPMS.Domain.Entities.Service", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("ApiKey") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("ApiKeyCreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("ApnsBundleId") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("ApnsKeyId") + .HasMaxLength(10) + .HasColumnType("varchar(10)"); + + b.Property("ApnsPrivateKey") + .HasColumnType("text"); + + b.Property("ApnsTeamId") + .HasMaxLength(10) + .HasColumnType("varchar(10)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CreatedBy") + .HasColumnType("bigint"); + + b.Property("DeletedAt") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.Property("FcmCredentials") + .HasColumnType("text"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false); + + b.Property("ServiceCode") + .IsRequired() + .HasMaxLength(8) + .HasColumnType("varchar(8)"); + + b.Property("ServiceName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("Status") + .HasColumnType("tinyint"); + + b.Property("SubStartedAt") + .HasColumnType("datetime(6)"); + + b.Property("SubTier") + .HasColumnType("tinyint"); + + b.Property("Tags") + .HasColumnType("json"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.Property("WebhookUrl") + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.HasKey("Id"); + + b.HasIndex("CreatedBy"); + + b.HasIndex("ServiceCode") + .IsUnique(); + + b.ToTable("Service", (string)null); + }); + + modelBuilder.Entity("SPMS.Domain.Entities.ServiceIp", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("IpAddress") + .IsRequired() + .HasMaxLength(45) + .HasColumnType("varchar(45)"); + + b.Property("ServiceId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("ServiceId"); + + b.ToTable("ServiceIp", (string)null); + }); + + modelBuilder.Entity("SPMS.Domain.Entities.SystemLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Action") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("AdminId") + .HasColumnType("bigint"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Details") + .HasColumnType("json"); + + b.Property("IpAddress") + .HasMaxLength(45) + .HasColumnType("varchar(45)"); + + b.Property("ServiceId") + .HasColumnType("bigint"); + + b.Property("TargetId") + .HasColumnType("bigint"); + + b.Property("TargetType") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("AdminId"); + + b.HasIndex("CreatedAt"); + + b.HasIndex("ServiceId"); + + b.ToTable("SystemLog", (string)null); + }); + + modelBuilder.Entity("SPMS.Domain.Entities.WebhookLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("EventType") + .HasColumnType("tinyint"); + + b.Property("Payload") + .IsRequired() + .HasColumnType("json"); + + b.Property("ResponseBody") + .HasColumnType("text"); + + b.Property("ResponseCode") + .HasColumnType("int"); + + b.Property("SentAt") + .HasColumnType("datetime(6)"); + + b.Property("ServiceId") + .HasColumnType("bigint"); + + b.Property("Status") + .HasColumnType("tinyint"); + + b.Property("WebhookUrl") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("varchar(500)"); + + b.HasKey("Id"); + + b.HasIndex("ServiceId", "SentAt"); + + b.ToTable("WebhookLog", (string)null); + }); + + modelBuilder.Entity("SPMS.Domain.Entities.DailyStat", b => + { + b.HasOne("SPMS.Domain.Entities.Service", "Service") + .WithMany() + .HasForeignKey("ServiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Service"); + }); + + modelBuilder.Entity("SPMS.Domain.Entities.Device", b => + { + b.HasOne("SPMS.Domain.Entities.Service", "Service") + .WithMany("Devices") + .HasForeignKey("ServiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Service"); + }); + + modelBuilder.Entity("SPMS.Domain.Entities.FileEntity", b => + { + b.HasOne("SPMS.Domain.Entities.Admin", "CreatedByAdmin") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("SPMS.Domain.Entities.Service", "Service") + .WithMany() + .HasForeignKey("ServiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CreatedByAdmin"); + + b.Navigation("Service"); + }); + + modelBuilder.Entity("SPMS.Domain.Entities.Message", b => + { + b.HasOne("SPMS.Domain.Entities.Admin", "CreatedByAdmin") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("SPMS.Domain.Entities.Service", "Service") + .WithMany("Messages") + .HasForeignKey("ServiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CreatedByAdmin"); + + b.Navigation("Service"); + }); + + modelBuilder.Entity("SPMS.Domain.Entities.Payment", b => + { + b.HasOne("SPMS.Domain.Entities.Admin", "Admin") + .WithMany() + .HasForeignKey("AdminId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("SPMS.Domain.Entities.Service", "Service") + .WithMany() + .HasForeignKey("ServiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Admin"); + + b.Navigation("Service"); + }); + + modelBuilder.Entity("SPMS.Domain.Entities.PushOpenLog", b => + { + b.HasOne("SPMS.Domain.Entities.Device", "Device") + .WithMany() + .HasForeignKey("DeviceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("SPMS.Domain.Entities.Message", "Message") + .WithMany() + .HasForeignKey("MessageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("SPMS.Domain.Entities.Service", "Service") + .WithMany() + .HasForeignKey("ServiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Device"); + + b.Navigation("Message"); + + b.Navigation("Service"); + }); + + modelBuilder.Entity("SPMS.Domain.Entities.PushSendLog", b => + { + b.HasOne("SPMS.Domain.Entities.Device", "Device") + .WithMany() + .HasForeignKey("DeviceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("SPMS.Domain.Entities.Message", "Message") + .WithMany() + .HasForeignKey("MessageId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("SPMS.Domain.Entities.Service", "Service") + .WithMany() + .HasForeignKey("ServiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Device"); + + b.Navigation("Message"); + + b.Navigation("Service"); + }); + + modelBuilder.Entity("SPMS.Domain.Entities.Service", b => + { + b.HasOne("SPMS.Domain.Entities.Admin", "CreatedByAdmin") + .WithMany() + .HasForeignKey("CreatedBy") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("CreatedByAdmin"); + }); + + modelBuilder.Entity("SPMS.Domain.Entities.ServiceIp", b => + { + b.HasOne("SPMS.Domain.Entities.Service", "Service") + .WithMany("ServiceIps") + .HasForeignKey("ServiceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Service"); + }); + + modelBuilder.Entity("SPMS.Domain.Entities.SystemLog", b => + { + b.HasOne("SPMS.Domain.Entities.Admin", "Admin") + .WithMany() + .HasForeignKey("AdminId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("SPMS.Domain.Entities.Service", "Service") + .WithMany() + .HasForeignKey("ServiceId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Admin"); + + b.Navigation("Service"); + }); + + modelBuilder.Entity("SPMS.Domain.Entities.WebhookLog", b => + { + b.HasOne("SPMS.Domain.Entities.Service", "Service") + .WithMany() + .HasForeignKey("ServiceId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Service"); + }); + + modelBuilder.Entity("SPMS.Domain.Entities.Service", b => + { + b.Navigation("Devices"); + + b.Navigation("Messages"); + + b.Navigation("ServiceIps"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SPMS.Infrastructure/Migrations/20260209042244_ApplyDomainEnums.cs b/SPMS.Infrastructure/Migrations/20260209042244_ApplyDomainEnums.cs new file mode 100644 index 0000000..aac71d3 --- /dev/null +++ b/SPMS.Infrastructure/Migrations/20260209042244_ApplyDomainEnums.cs @@ -0,0 +1,38 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace SPMS.Infrastructure.Migrations +{ + /// + public partial class ApplyDomainEnums : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "EventType", + table: "WebhookLog", + type: "tinyint", + nullable: false, + oldClrType: typeof(string), + oldType: "varchar(50)", + oldMaxLength: 50) + .OldAnnotation("MySql:CharSet", "utf8mb4"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "EventType", + table: "WebhookLog", + type: "varchar(50)", + maxLength: 50, + nullable: false, + oldClrType: typeof(sbyte), + oldType: "tinyint") + .Annotation("MySql:CharSet", "utf8mb4"); + } + } +} diff --git a/SPMS.Infrastructure/Migrations/AppDbContextModelSnapshot.cs b/SPMS.Infrastructure/Migrations/AppDbContextModelSnapshot.cs index d91db2f..bad846c 100644 --- a/SPMS.Infrastructure/Migrations/AppDbContextModelSnapshot.cs +++ b/SPMS.Infrastructure/Migrations/AppDbContextModelSnapshot.cs @@ -603,10 +603,8 @@ namespace SPMS.Infrastructure.Migrations MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - b.Property("EventType") - .IsRequired() - .HasMaxLength(50) - .HasColumnType("varchar(50)"); + b.Property("EventType") + .HasColumnType("tinyint"); b.Property("Payload") .IsRequired() diff --git a/SPMS.Infrastructure/Persistence/Configurations/WebhookLogConfiguration.cs b/SPMS.Infrastructure/Persistence/Configurations/WebhookLogConfiguration.cs index 8043923..a2e5989 100644 --- a/SPMS.Infrastructure/Persistence/Configurations/WebhookLogConfiguration.cs +++ b/SPMS.Infrastructure/Persistence/Configurations/WebhookLogConfiguration.cs @@ -15,7 +15,7 @@ public class WebhookLogConfiguration : IEntityTypeConfiguration builder.Property(e => e.ServiceId).IsRequired(); builder.Property(e => e.WebhookUrl).HasMaxLength(500).IsRequired(); - builder.Property(e => e.EventType).HasMaxLength(50).IsRequired(); + builder.Property(e => e.EventType).HasColumnType("tinyint").IsRequired(); builder.Property(e => e.Payload).HasColumnType("json").IsRequired(); builder.Property(e => e.Status).HasColumnType("tinyint").IsRequired(); builder.Property(e => e.ResponseCode); -- 2.45.1