| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- using System.ComponentModel.DataAnnotations;
- using System.ComponentModel.DataAnnotations.Schema;
- using Domain.Entities.Donations.ValueObject;
- using Domain.Entities.Members;
- namespace Domain.Entities.Donations;
- public class WithdrawalRequest
- {
- [ForeignKey(nameof(ChannelID))]
- public virtual Channel? Channel { get; private set; }
- [ForeignKey(nameof(MemberID))]
- public virtual Member? Member { get; private set; }
- [Key]
- public int ID { get; private set; }
- public int ChannelID { get; private set; }
- public int MemberID { get; private set; }
- public int RequestedAmount { get; private set; }
- /// <summary>
- /// 후원 수익(Donation) 잔액에서 차감되는 금액. RequestedAmount = DonationAmount + StoreRevenueAmount.
- /// 정산서 명세에 분리 표시 (출처 보존).
- /// </summary>
- public int DonationAmount { get; private set; }
- /// <summary>
- /// 상품 판매 수익(StoreRevenue) 잔액에서 차감되는 금액. RequestedAmount = DonationAmount + StoreRevenueAmount.
- /// 정산서 명세에 분리 표시 (출처 보존).
- /// </summary>
- public int StoreRevenueAmount { get; private set; }
- public int IncomeTax { get; private set; }
- public int LocalTax { get; private set; }
- public int WithholdingTax { get; private set; }
- public int NetAmount { get; private set; }
- public WithdrawalStatus Status { get; private set; } = WithdrawalStatus.Pending;
- public string BankCode { get; private set; } = default!;
- public string BankName { get; private set; } = default!;
- public string AccountNumber { get; private set; } = default!;
- public string AccountHolder { get; private set; } = default!;
- public DateTime RequestedAt { get; private set; } = DateTime.UtcNow;
- public DateTime? ProcessedAt { get; private set; }
- public string? RejectedReason { get; private set; }
- public string? AdminMemo { get; private set; }
- private WithdrawalRequest() { }
- /// <summary>
- /// 기존(후원 단일) 출금 요청 생성. RequestedAmount 전액을 DonationAmount로 분배.
- /// 신규 코드(상점 수익 분개)는 분리 시그니처 Create(channelID, memberID, donationAmount, storeRevenueAmount, ...) 사용.
- /// </summary>
- public static WithdrawalRequest Create(
- int channelID,
- int memberID,
- int requestedAmount,
- string bankCode,
- string bankName,
- string accountNumber,
- string accountHolder
- ) => Create(
- channelID: channelID,
- memberID: memberID,
- donationAmount: requestedAmount,
- storeRevenueAmount: 0,
- bankCode: bankCode,
- bankName: bankName,
- accountNumber: accountNumber,
- accountHolder: accountHolder
- );
- /// <summary>
- /// 후원/상점 분개 출금 요청 생성. 정산서 명세에 두 잔액 출처를 분리 표시.
- /// </summary>
- public static WithdrawalRequest Create(
- int channelID,
- int memberID,
- int donationAmount,
- int storeRevenueAmount,
- string bankCode,
- string bankName,
- string accountNumber,
- string accountHolder
- ) {
- if (donationAmount < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(donationAmount), "Donation amount must be non-negative.");
- }
- if (storeRevenueAmount < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(storeRevenueAmount), "StoreRevenue amount must be non-negative.");
- }
- var requestedAmount = donationAmount + storeRevenueAmount;
- if (requestedAmount <= 0)
- {
- throw new ArgumentOutOfRangeException(nameof(requestedAmount), "Total withdrawal amount must be positive.");
- }
- var incomeTax = (int)Math.Floor(requestedAmount * 3m / 100m);
- var localTax = (int)Math.Floor(requestedAmount * 3m / 1000m);
- var withholdingTax = incomeTax + localTax;
- return new WithdrawalRequest
- {
- ChannelID = channelID,
- MemberID = memberID,
- RequestedAmount = requestedAmount,
- DonationAmount = donationAmount,
- StoreRevenueAmount = storeRevenueAmount,
- IncomeTax = incomeTax,
- LocalTax = localTax,
- WithholdingTax = withholdingTax,
- NetAmount = requestedAmount - withholdingTax,
- BankCode = bankCode,
- BankName = bankName,
- AccountNumber = accountNumber,
- AccountHolder = accountHolder
- };
- }
- public void MarkProcessing(string? adminMemo = null)
- {
- Status = WithdrawalStatus.Processing;
- AdminMemo = adminMemo;
- }
- public void Complete(string? adminMemo = null)
- {
- Status = WithdrawalStatus.Completed;
- ProcessedAt = DateTime.UtcNow;
- AdminMemo = adminMemo;
- }
- public void Reject(string reason, string? adminMemo = null)
- {
- Status = WithdrawalStatus.Rejected;
- ProcessedAt = DateTime.UtcNow;
- RejectedReason = reason;
- AdminMemo = adminMemo;
- }
- }
|