using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using Domain.Entities.Store.ValueObject; namespace Domain.Entities.Store; /// /// 환불 단위 — 쿠폰 1개 = 1행. OrderRefund 1건에 N개의 OrderRefundItem (일괄 환불 지원). /// /// 설계 이유: OrderRefund 자체는 Amount 합계만 가지고 있어 어떤 쿠폰/OrderItem 이 /// 환불되는지 추적 불가. 이 테이블이 정확한 환불 대상 + 후처리(회수/만료) 정책을 보관. /// /// ProcessRefund 시 이 행들을 순회해: /// - 다날 부분 취소 (OrderRefund.Amount 단위로 1회) /// - 각 CouponCode 에 PostRefundAction 적용 (Restore / Expire) /// - MemberInventory 의 해당 행 제거 /// public class OrderRefundItem { [ForeignKey(nameof(OrderRefundID))] public virtual OrderRefund? OrderRefund { 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 OrderRefundID { get; private set; } public int OrderItemID { get; private set; } public int CouponCodeID { get; private set; } /// 환불 단가 (스냅샷). OrderItem.UnitPrice 와 동일하지만 OrderItem 가격 변동 대비 보관. public int UnitAmount { get; private set; } public CouponPostRefundAction PostRefundAction { get; private set; } public DateTime CreatedAt { get; private set; } = DateTime.UtcNow; private OrderRefundItem() { } public static OrderRefundItem Create(int orderRefundID, int orderItemID, int couponCodeID, int unitAmount, CouponPostRefundAction action) { if (orderRefundID <= 0) { throw new ArgumentOutOfRangeException(nameof(orderRefundID)); } if (orderItemID <= 0) { throw new ArgumentOutOfRangeException(nameof(orderItemID)); } if (couponCodeID <= 0) { throw new ArgumentOutOfRangeException(nameof(couponCodeID)); } if (unitAmount <= 0) { throw new ArgumentOutOfRangeException(nameof(unitAmount), "UnitAmount must be positive."); } return new OrderRefundItem { OrderRefundID = orderRefundID, OrderItemID = orderItemID, CouponCodeID = couponCodeID, UnitAmount = unitAmount, PostRefundAction = action }; } }