| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- using System.ComponentModel.DataAnnotations;
- using System.ComponentModel.DataAnnotations.Schema;
- using Domain.Entities.Members;
- namespace Domain.Entities.Store;
- /// <summary>
- /// 회원 보관함. Digital 상품 결제 완료 시 1 row INSERT.
- /// 사용자가 보관함에서 "사용" 누르면 UsedAt 마킹 + CouponCode.MarkUsed() 호출.
- /// </summary>
- public class MemberInventory
- {
- [ForeignKey(nameof(MemberID))]
- public virtual Member? Member { get; private set; }
- [ForeignKey(nameof(OrderItemID))]
- public virtual OrderItem? OrderItem { get; private set; }
- [ForeignKey(nameof(CouponCodeID))]
- public virtual CouponCode? CouponCode { get; private set; }
- [Key]
- public int ID { get; private set; }
- public int MemberID { get; private set; }
- public int OrderItemID { get; private set; }
- public int CouponCodeID { get; private set; }
- public DateTime AcquiredAt { get; private set; } = DateTime.UtcNow;
- /// <summary>사용자가 "사용" 클릭한 시점 (코드 노출 후). null = 미사용.</summary>
- public DateTime? UsedAt { get; private set; }
- /// <summary>쿠폰 만료 일시 (Coupon.ExpiresAt 스냅샷). 만료 후 보관함에서 자동 제외.</summary>
- public DateTime? ExpiresAt { get; private set; }
- /// <summary>사용자 보관함에서 소프트 삭제된 일시. null = 보관함 노출. 값 있음 = 사용자 화면에서 숨김 (DB 행은 보존, 환불·통계에 사용).</summary>
- public DateTime? DeletedAt { get; private set; }
- private MemberInventory() { }
- public static MemberInventory Create(int memberID, int orderItemID, int couponCodeID, DateTime? expiresAt = null)
- {
- if (memberID <= 0)
- {
- throw new ArgumentOutOfRangeException(nameof(memberID));
- }
- if (orderItemID <= 0)
- {
- throw new ArgumentOutOfRangeException(nameof(orderItemID));
- }
- if (couponCodeID <= 0)
- {
- throw new ArgumentOutOfRangeException(nameof(couponCodeID));
- }
- return new MemberInventory
- {
- MemberID = memberID,
- OrderItemID = orderItemID,
- CouponCodeID = couponCodeID,
- ExpiresAt = expiresAt
- };
- }
- public void MarkUsed()
- {
- if (UsedAt.HasValue)
- {
- throw new InvalidOperationException("이미 사용한 쿠폰입니다.");
- }
- UsedAt = DateTime.UtcNow;
- }
- /// <summary>
- /// 사용자 보관함에서 소프트 삭제. DB row 는 유지되며 DeletedAt 만 마킹.
- /// 환불 시점에는 DeletedAt 무시하고 정상 처리 (refund handler 가 모든 inventory 를 본다).
- /// </summary>
- public void SoftDelete()
- {
- if (DeletedAt.HasValue)
- {
- throw new InvalidOperationException("이미 삭제된 보관함 항목입니다.");
- }
- DeletedAt = DateTime.UtcNow;
- }
- /// <summary>
- /// 관리자가 연결된 CouponCode 를 일괄 만료시킬 때 호출. ExpiresAt 을 즉시 now 로 설정해
- /// 회원 보관함에서 자연 만료된 것처럼 표시되도록 한다 (기존 IsExpired UI 재사용).
- /// </summary>
- public void ForceExpire()
- {
- ExpiresAt = DateTime.UtcNow;
- }
- /// <summary>
- /// 관리자가 만료 처리한 CouponCode 를 복귀시킬 때 호출. ExpiresAt 을 null 로 해제 (영구 사용 가능 상태).
- /// </summary>
- public void ClearExpiry()
- {
- ExpiresAt = null;
- }
- }
|