Handler.cs 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. using Application.Abstractions.Data;
  2. using Application.Abstractions.Messaging;
  3. using Domain.Entities.Donations.ValueObject;
  4. using Microsoft.EntityFrameworkCore;
  5. using SharedKernel.Results;
  6. namespace Application.Features.Api.Studio.Wallet.GetBalance;
  7. internal sealed class Handler(IAppDbContext db) : IQueryHandler<Query, Result<Response>>
  8. {
  9. private static readonly Response Empty = new(0, 0, 0, 0, []);
  10. public async Task<Result<Response>> Handle(Query request, CancellationToken ct)
  11. {
  12. var channel = await db.Channel.AsNoTracking().FirstOrDefaultAsync(c => c.MemberID == request.MemberID && c.IsActive, ct);
  13. if (channel is null)
  14. {
  15. return Result.Success(Empty);
  16. }
  17. // Wallet Donation 잔액
  18. var wallet = await db.Wallet.AsNoTracking()
  19. .Include(w => w.Balances)
  20. .FirstOrDefaultAsync(w => w.MemberID == request.MemberID, ct);
  21. var withdrawableBalance = 0;
  22. if (wallet is not null)
  23. {
  24. var donationBal = wallet.Balances.FirstOrDefault(b => b.Type == Domain.Entities.Wallets.ValueObject.WalletBalanceType.Donation);
  25. if (donationBal is not null)
  26. {
  27. withdrawableBalance = (int)donationBal.Amount.Value;
  28. }
  29. }
  30. // 누적 수익 (Donation NetAmount 합계)
  31. var totalEarned = await db.Donation.AsNoTracking()
  32. .Where(d => d.ReceiverMemberID == request.MemberID && !d.IsTest)
  33. .SumAsync(d => d.NetAmount, ct);
  34. // 누적 출금 (완료된 출금 합계)
  35. var totalWithdrawn = await db.WithdrawalRequest.AsNoTracking()
  36. .Where(w => w.MemberID == request.MemberID && w.Status == WithdrawalStatus.Completed)
  37. .SumAsync(w => w.NetAmount, ct);
  38. // 대기 중 출금
  39. var pendingWithdrawal = await db.WithdrawalRequest.AsNoTracking()
  40. .Where(w => w.MemberID == request.MemberID && (w.Status == WithdrawalStatus.Pending || w.Status == WithdrawalStatus.Processing))
  41. .SumAsync(w => w.RequestedAmount, ct);
  42. // 최근 거래 내역 10건
  43. var recentTx = await db.WalletTransaction.AsNoTracking()
  44. .Where(t => t.Wallet!.MemberID == request.MemberID && t.BalanceType == Domain.Entities.Wallets.ValueObject.WalletBalanceType.Donation)
  45. .OrderByDescending(t => t.CreatedAt)
  46. .Take(10)
  47. .Select(t => new TransactionItem(
  48. t.ID,
  49. t.TxType.ToString(),
  50. (int)t.Amount.Value,
  51. (int)t.BalanceAfter.Value,
  52. t.Memo ?? "",
  53. t.CreatedAt
  54. ))
  55. .ToListAsync(ct);
  56. return Result.Success(new Response(
  57. withdrawableBalance,
  58. totalEarned,
  59. totalWithdrawn,
  60. pendingWithdrawal,
  61. recentTx
  62. ));
  63. }
  64. }