using Domain.Entities.Wallets.ValueObject; using Infrastructure.Persistence.Identity; using Application.Abstractions.Messaging; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using System.ComponentModel; using System.ComponentModel.DataAnnotations; namespace Admin.Pages.Member.Wallet.List; public class ViewModel(IMediator mediator, UserManager userManager) : PageModel { public WalletInfo Wallet { get; set; } = new(); public MemberInfo Member { get; set; } = new(); [BindProperty] [Required(ErrorMessage = "충전 금액을 입력해주세요.")] [Range(-99999999, 99999999, ErrorMessage = "금액은 -99,999,999 ~ 99,999,999 범위입니다.")] [DisplayName("충전 금액")] public long Amount { get; set; } [BindProperty] [DisplayName("잔액 유형")] public WalletBalanceType? BalanceType { get; set; } [BindProperty] [Required(ErrorMessage = "비밀번호를 입력해주세요.")] [DisplayName("비밀번호")] public string Password { get; set; } = default!; [BindProperty] [MaxLength(1000, ErrorMessage = "메모는 {1}자 이하로 입력하세요.")] [DisplayName("메모")] public string? Memo { get; set; } public sealed class WalletInfo { public int ID { get; set; } public string Balance { get; set; } = "0"; public List Balances { get; set; } = []; } public sealed record BalanceRow( WalletBalanceType Type, string TypeName, string Amount ); public static string GetBalanceTypeName(WalletBalanceType type) => type switch { WalletBalanceType.PgCharged => "PG 충전", WalletBalanceType.Deposit => "직접 입금", WalletBalanceType.Donation => "후원", WalletBalanceType.Reward => "보상", WalletBalanceType.Airdrop => "에어드랍", WalletBalanceType.Locked => "잠금", WalletBalanceType.Adjusted => "조정", WalletBalanceType.StoreRevenue => "상점 수익", _ => type.ToString() }; public sealed class MemberInfo { public int ID { get; set; } public string Email { get; set; } = default!; public string? GradeName { get; set; } } public async Task OnGetAsync(int id, CancellationToken ct) { var walletResult = await mediator.Send(new GetWallet.Query(id), ct); if (walletResult.IsFailure) { TempData["ErrorMessages"] = walletResult.Error.Description; return RedirectToPage("Index"); } var result = walletResult.Value; Wallet = new WalletInfo { ID = result.WalletID, Balance = result.Balance.ToString("N0"), Balances = [..result.Balances.Select(c => new BalanceRow(c.Type, GetBalanceTypeName(c.Type), c.Amount.ToString("N0")))] }; Member = new MemberInfo { ID = result.MemberID, Email = result.MemberEmail, GradeName = result.GradeName }; return Page(); } public async Task OnPostChargeAsync(int id, CancellationToken ct) { if (Amount == 0) { TempData["ErrorMessages"] = "충전 금액을 입력해주세요."; return RedirectToPage("View", new { id }); } var admin = await userManager.GetUserAsync(User); if (admin is null || !await userManager.CheckPasswordAsync(admin, Password)) { TempData["ErrorMessages"] = "비밀번호가 올바르지 않습니다."; return RedirectToPage("View", new { id }); } var result = await mediator.Send(new ChargeWallet.Command( id, Amount, Memo, BalanceType ), ct); if (result.IsFailure) { TempData["ErrorMessages"] = result.Error.Description; } else { TempData["SuccessMessage"] = Amount > 0 ? $"{Amount:N0}P 충전되었습니다." : $"{Math.Abs(Amount):N0}P 차감되었습니다."; } return RedirectToPage("View", new { id }); } }