using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace Domain.Entities.Members.Logs; /// /// 경험치 변동 내역 /// public class MemberExpLog { [ForeignKey(nameof(MemberID))] public virtual Member Member { get; private set; } = null!; [ForeignKey(nameof(BroadcastSessionID))] public virtual BroadcastSession? BroadcastSession { get; private set; } [Key] public int ID { get; private set; } public int MemberID { get; private set; } /// 방송 세션 단위로 리더보드 집계 (null = 방송 외 적립) public int? BroadcastSessionID { get; private set; } /// 채널 문맥 (channel 단위 조회용, null = 전역) public int? ChannelID { get; private set; } public string Reason { get; private set; } = default!; public int Amount { get; private set; } public long Balance { get; private set; } public DateTime CreatedAt { get; private set; } = DateTime.UtcNow; private MemberExpLog() { } private MemberExpLog(int memberID, string reason, int amount, long balance, int? broadcastSessionID, int? channelID) { if (memberID <= 0) { throw new ArgumentOutOfRangeException(nameof(memberID)); } if (string.IsNullOrWhiteSpace(reason)) { throw new ArgumentException("Reason is required.", nameof(reason)); } if (reason.Length > 200) { throw new ArgumentOutOfRangeException(nameof(reason)); } MemberID = memberID; Reason = reason; Amount = amount; Balance = balance; BroadcastSessionID = broadcastSessionID; ChannelID = channelID; CreatedAt = DateTime.UtcNow; } public static MemberExpLog Create(int memberID, string reason, int amount, long balance) { return new(memberID, reason, amount, balance, null, null); } /// 방송 중 적립 (채팅/후원 XP) — 리더보드 집계 대상 public static MemberExpLog CreateForBroadcast(int memberID, string reason, int amount, long balance, int broadcastSessionID, int channelID) { return new(memberID, reason, amount, balance, broadcastSessionID, channelID); } }