Handler.cs 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. using Application.Abstractions.Messaging;
  2. using Application.Abstractions.Data;
  3. using SharedKernel.Results;
  4. using Domain.Entities.Common.ValueObject;
  5. using Domain.Entities.Wallets.ValueObject;
  6. using Microsoft.EntityFrameworkCore;
  7. namespace Application.Features.Admin.Member.Wallet.List.Charge;
  8. public sealed class Handler(IAppDbContext db) : ICommandHandler<Command, Result>
  9. {
  10. public async Task<Result> Handle(Command request, CancellationToken ct)
  11. {
  12. var wallet = await db.Wallet.Include(x => x.Balances).Include(x => x.Transactions).FirstOrDefaultAsync(x => x.ID == request.WalletID, ct);
  13. if (wallet is null)
  14. {
  15. return Result.Failure(Error.NotFound("Wallet.NotFound", "지갑을 찾을 수 없습니다."));
  16. }
  17. if (request.BalanceType == WalletBalanceType.Locked)
  18. {
  19. return Result.Failure(Error.Problem("Wallet.LockedNotAdjustable", "잠금 잔액은 직접 조정할 수 없습니다."));
  20. }
  21. var amount = Money.KRW(Math.Abs(request.Amount));
  22. var reason = request.Amount > 0 ? "관리자 충전" : "관리자 차감";
  23. if (request.Amount > 0)
  24. {
  25. if (request.BalanceType.HasValue)
  26. {
  27. wallet.AdjustIncrease(request.BalanceType.Value, amount, reason, memo: request.Memo);
  28. }
  29. else
  30. {
  31. wallet.AdjustIncrease(amount, reason, memo: request.Memo);
  32. }
  33. }
  34. else if (request.Amount < 0)
  35. {
  36. if (request.BalanceType.HasValue)
  37. {
  38. // 지정 잔액 단일 차감 — 구지갑은 해당 유형 row 가 없을 수 있어 컬렉션에서 직접 조회
  39. var typeBalance = wallet.Balances.SingleOrDefault(x => x.Type == request.BalanceType.Value)?.Amount.Value ?? 0;
  40. if (typeBalance < amount.Value)
  41. {
  42. return Result.Failure(Error.Problem("Wallet.InsufficientBalance", "선택한 잔액 유형의 차감 가능 금액이 부족합니다."));
  43. }
  44. wallet.AdjustDecrease(request.BalanceType.Value, amount, reason, memo: request.Memo);
  45. }
  46. else
  47. {
  48. if (wallet.GetTotalAvailable().Value < amount.Value)
  49. {
  50. return Result.Failure(Error.Problem("Wallet.InsufficientBalance", "차감 가능한 잔액이 부족합니다."));
  51. }
  52. wallet.AdjustDecreaseAcrossBalances(amount, reason, memo: request.Memo);
  53. }
  54. }
  55. else
  56. {
  57. return Result.Failure(Error.Problem("Wallet.AmountRequired", "충전 금액을 입력해주세요."));
  58. }
  59. await db.SaveChangesAsync(ct);
  60. return Result.Success();
  61. }
  62. }