using SharedKernel.Extensions; using MediatR; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using System.ComponentModel; using System.ComponentModel.DataAnnotations; namespace Admin.Pages.Store.Game; /// /// 게임별 인앱 상품 SKU 정가 카탈로그 관리. /// 파트너 결제 보고(/v1/purchases) 금액 검증용 — 보고가가 정가와 다르면 불일치 flag. /// public class CatalogModel(IMediator mediator) : PageModel { public Application.Features.Admin.Store.GameCatalog.GetByGame.Response? Data { get; private set; } [BindProperty] public AddInput Add { get; set; } = new(); public sealed class AddInput { public int GameID { get; set; } [DisplayName("SKU(상품 ID)")] [Required(ErrorMessage = "{0}은(는) 필수입니다.")] [StringLength(100, ErrorMessage = "{0}은(는) {1}자 이하로 입력하세요.")] public string ProductID { get; set; } = null!; [DisplayName("정가(원)")] [Range(1, int.MaxValue, ErrorMessage = "{0}은(는) 1 이상이어야 합니다.")] public int Price { get; set; } } public async Task OnGetAsync(int id, CancellationToken ct) { var result = await mediator.Send(new Application.Features.Admin.Store.GameCatalog.GetByGame.Query(id), ct); if (result.IsFailure) { TempData["ErrorMessages"] = result.Error.Description; return; } Data = result.Value; Add.GameID = id; } public async Task OnPostAddAsync(CancellationToken ct) { if (!ModelState.IsValid) { TempData["ErrorMessages"] = ModelState.GetErrorMessages(); return Redirect($"/Store/Game/Catalog/{Add.GameID}"); } var result = await mediator.Send(new Application.Features.Admin.Store.GameCatalog.Create.Command(Add.GameID, Add.ProductID, Add.Price), ct); if (result.IsFailure) { TempData["ErrorMessages"] = result.Error.Description; } else { TempData["SuccessMessage"] = $"SKU {Add.ProductID} 가 등록되었습니다."; } return Redirect($"/Store/Game/Catalog/{Add.GameID}"); } public async Task OnPostUpdateAsync(int gameID, int id, int price, bool isActive, CancellationToken ct) { var result = await mediator.Send(new Application.Features.Admin.Store.GameCatalog.Update.Command(id, price, isActive), ct); if (result.IsFailure) { TempData["ErrorMessages"] = result.Error.Description; } else { TempData["SuccessMessage"] = "카탈로그 항목이 수정되었습니다."; } return Redirect($"/Store/Game/Catalog/{gameID}"); } public async Task OnPostDeleteAsync(int gameID, int id, CancellationToken ct) { var result = await mediator.Send(new Application.Features.Admin.Store.GameCatalog.Delete.Command(id), ct); if (result.IsFailure) { TempData["ErrorMessages"] = result.Error.Description; } else { TempData["SuccessMessage"] = "카탈로그 항목이 삭제되었습니다."; } return Redirect($"/Store/Game/Catalog/{gameID}"); } }