Detail.cshtml.cs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. using SharedKernel.Extensions;
  2. using Application.Abstractions.Messaging;
  3. using Microsoft.AspNetCore.Mvc;
  4. using Microsoft.AspNetCore.Mvc.RazorPages;
  5. using System.ComponentModel;
  6. using System.ComponentModel.DataAnnotations;
  7. namespace Admin.Pages.Store.Shipment;
  8. public class DetailModel(IMediator mediator) : PageModel
  9. {
  10. public GetShipment.Response? Data { get; private set; }
  11. [BindProperty(SupportsGet = true)]
  12. public bool WithAddress { get; set; }
  13. [BindProperty]
  14. public TrackingInput Tracking { get; set; } = new();
  15. public sealed class TrackingInput
  16. {
  17. [DisplayName("택배사")]
  18. [Required(ErrorMessage = "{0}은(는) 필수입니다.")]
  19. [StringLength(50)]
  20. public string Carrier { get; set; } = null!;
  21. [DisplayName("송장번호")]
  22. [Required(ErrorMessage = "{0}은(는) 필수입니다.")]
  23. [StringLength(50)]
  24. public string TrackingNumber { get; set; } = null!;
  25. }
  26. [BindProperty]
  27. public BillingInput Billing { get; set; } = new();
  28. public sealed class BillingInput
  29. {
  30. [DisplayName("배송비")]
  31. [Range(0, int.MaxValue, ErrorMessage = "{0}은(는) 0 이상이어야 합니다.")]
  32. public int ShippingFee { get; set; }
  33. [DisplayName("관리자 메모")]
  34. [StringLength(500, ErrorMessage = "{0}은(는) 최대 {1}자까지 입력 가능합니다.")]
  35. public string? AdminMemo { get; set; }
  36. }
  37. public async Task OnGetAsync(int id, CancellationToken ct)
  38. {
  39. await LoadAsync(id, ct);
  40. }
  41. public async Task<IActionResult> OnPostRegisterTrackingAsync(int id, CancellationToken ct)
  42. {
  43. if (!ModelState.IsValid)
  44. {
  45. TempData["ErrorMessages"] = ModelState.GetErrorMessages();
  46. return RedirectToPage("/Store/Shipment/Detail", new { id });
  47. }
  48. var result = await mediator.Send(new UpdateShipmentStatus.Command(
  49. id, "RegisterTracking", Tracking.Carrier, Tracking.TrackingNumber
  50. ), ct);
  51. if (result.IsFailure)
  52. {
  53. TempData["ErrorMessages"] = result.Error.Description;
  54. }
  55. else
  56. {
  57. TempData["SuccessMessage"] = "송장이 등록되었습니다.";
  58. }
  59. return RedirectToPage("/Store/Shipment/Detail", new { id });
  60. }
  61. public async Task<IActionResult> OnPostTransitAsync(int id, CancellationToken ct)
  62. {
  63. var result = await mediator.Send(new UpdateShipmentStatus.Command(id, "InTransit"), ct);
  64. TempData[result.IsFailure ? "ErrorMessages" : "SuccessMessage"] =
  65. result.IsFailure ? result.Error.Description : "배송중으로 전환되었습니다.";
  66. return RedirectToPage("/Store/Shipment/Detail", new { id });
  67. }
  68. public async Task<IActionResult> OnPostDeliveredAsync(int id, CancellationToken ct)
  69. {
  70. var result = await mediator.Send(new UpdateShipmentStatus.Command(id, "Delivered"), ct);
  71. TempData[result.IsFailure ? "ErrorMessages" : "SuccessMessage"] =
  72. result.IsFailure ? result.Error.Description : "배송완료로 전환되었습니다.";
  73. return RedirectToPage("/Store/Shipment/Detail", new { id });
  74. }
  75. public async Task<IActionResult> OnPostFailedAsync(int id, CancellationToken ct)
  76. {
  77. var result = await mediator.Send(new UpdateShipmentStatus.Command(id, "Failed"), ct);
  78. TempData[result.IsFailure ? "ErrorMessages" : "SuccessMessage"] =
  79. result.IsFailure ? result.Error.Description : "배송실패로 표시되었습니다.";
  80. return RedirectToPage("/Store/Shipment/Detail", new { id });
  81. }
  82. public async Task<IActionResult> OnPostUpdateBillingAsync(int id, CancellationToken ct)
  83. {
  84. if (!ModelState.IsValid)
  85. {
  86. TempData["ErrorMessages"] = ModelState.GetErrorMessages();
  87. return RedirectToPage("/Store/Shipment/Detail", new { id });
  88. }
  89. var result = await mediator.Send(new UpdateShipmentStatus.Command(
  90. id, "UpdateBilling",
  91. ShippingFee: Billing.ShippingFee,
  92. AdminMemo: Billing.AdminMemo
  93. ), ct);
  94. TempData[result.IsFailure ? "ErrorMessages" : "SuccessMessage"] =
  95. result.IsFailure ? result.Error.Description : "배송비/메모가 저장되었습니다.";
  96. return RedirectToPage("/Store/Shipment/Detail", new { id });
  97. }
  98. private async Task LoadAsync(int id, CancellationToken ct)
  99. {
  100. // 1차에는 모든 관리자가 주소 조회 가능 (S5에서는 권한 분리 미적용)
  101. // 실제 운영에서는 Member.IsAdmin 또는 별도 "Store.ViewAddress" 권한 검증 필요
  102. var result = await mediator.Send(new GetShipment.Query(id, WithAddress: WithAddress), ct);
  103. if (result.IsFailure)
  104. {
  105. TempData["ErrorMessages"] = result.Error.Description;
  106. return;
  107. }
  108. Data = result.Value;
  109. // Billing 폼 기본값을 현재 값으로 채우기
  110. Billing.ShippingFee = Data.ShippingFee;
  111. Billing.AdminMemo = Data.AdminMemo;
  112. }
  113. }