Write.cshtml.cs 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. using Domain.Entities.Store.ValueObject;
  2. using SharedKernel.Extensions;
  3. using MediatR;
  4. using Microsoft.AspNetCore.Mvc;
  5. using Microsoft.AspNetCore.Mvc.RazorPages;
  6. using Microsoft.AspNetCore.Mvc.Rendering;
  7. using System.ComponentModel;
  8. using System.ComponentModel.DataAnnotations;
  9. namespace Admin.Pages.Store.Coupon;
  10. public class WriteModel(IMediator mediator) : PageModel
  11. {
  12. public List<SelectListItem> Games { get; set; } = [];
  13. public List<(int ID, int GameID, string Name)> Products { get; set; } = [];
  14. [BindProperty]
  15. public InputModel Input { get; set; } = new();
  16. public sealed class InputModel
  17. {
  18. [DisplayName("게임")]
  19. [Required(ErrorMessage = "{0}을(를) 선택하세요.")]
  20. [Range(1, int.MaxValue, ErrorMessage = "게임을 선택해 주세요.")]
  21. public int GameID { get; set; }
  22. [DisplayName("무형 상품")]
  23. [Required(ErrorMessage = "{0}을(를) 선택하세요.")]
  24. [Range(1, int.MaxValue, ErrorMessage = "상품을 선택해 주세요.")]
  25. public int ProductID { get; set; }
  26. [DisplayName("쿠폰명")]
  27. [Required(ErrorMessage = "{0}은(는) 필수입니다.")]
  28. [StringLength(200)]
  29. public string Name { get; set; } = null!;
  30. [DisplayName("사용 정책")]
  31. public CouponUsagePolicy UsagePolicy { get; set; } = CouponUsagePolicy.SingleUse;
  32. [DisplayName("만료 일시")]
  33. [DataType(DataType.DateTime)]
  34. public DateTime? ExpiresAt { get; set; }
  35. [DisplayName("재고 부족 알림 임계치")]
  36. [Range(0, int.MaxValue)]
  37. public int LowStockThreshold { get; set; } = 10;
  38. }
  39. public async Task OnGetAsync(CancellationToken ct)
  40. {
  41. await LoadDataAsync(ct);
  42. }
  43. public async Task<IActionResult> OnPostAsync(CancellationToken ct)
  44. {
  45. if (!ModelState.IsValid)
  46. {
  47. TempData["ErrorMessages"] = ModelState.GetErrorMessages();
  48. await LoadDataAsync(ct);
  49. return Page();
  50. }
  51. var result = await mediator.Send(new CreateCoupon.Command(
  52. Input.ProductID,
  53. Input.GameID,
  54. Input.Name,
  55. Input.UsagePolicy,
  56. Input.ExpiresAt,
  57. Input.LowStockThreshold
  58. ), ct);
  59. if (result.IsFailure)
  60. {
  61. TempData["ErrorMessages"] = result.Error.Description;
  62. await LoadDataAsync(ct);
  63. return Page();
  64. }
  65. TempData["SuccessMessage"] = $"{Input.Name} 쿠폰이 등록되었습니다. 코드 풀에서 CSV 업로드 진행하세요.";
  66. return RedirectToPage("/Store/Coupon/Codes", new { id = result.Value });
  67. }
  68. private async Task LoadDataAsync(CancellationToken ct)
  69. {
  70. var gamesResult = await mediator.Send(new GetGames.Query(true), ct);
  71. Games = [.. gamesResult.List.Select(g => new SelectListItem
  72. {
  73. Value = g.ID.ToString(),
  74. Text = $"{g.KorName} ({g.Publisher})"
  75. })];
  76. // 무형 상품만 (Coupon 은 무형 상품에 발급)
  77. var productsResult = await mediator.Send(new SearchProducts.Query(null, null, null, null, null, ProductType.Digital, true, 1, 1000), ct);
  78. Products = [.. productsResult.List.Select(p => (p.ID, p.GameID, p.Name))];
  79. }
  80. }