Index.cshtml.cs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. using Application.Abstractions.Messaging;
  2. using Microsoft.AspNetCore.Mvc;
  3. using Microsoft.AspNetCore.Mvc.RazorPages;
  4. using SharedKernel.Extensions;
  5. using System.ComponentModel.DataAnnotations;
  6. using System.Globalization;
  7. namespace Admin.Pages.Stocks.MarketHoliday;
  8. /// <summary>
  9. /// KRX 휴장일 관리 — 목록(연도 필터)/추가/삭제. 수집 배치(KrxBackfill/MarketCalendar)의 영업일 판정에 사용되므로
  10. /// 거래일을 휴장일로 잘못 등록하면 해당 날짜 데이터가 영구 결손된다 (추가/삭제 모두 confirm).
  11. /// </summary>
  12. public class IndexModel(IMediator mediator) : PageModel
  13. {
  14. public int? Year { get; private set; }
  15. public int Total { get; private set; }
  16. public List<int> Years { get; private set; } = [];
  17. public List<(
  18. DateOnly Date,
  19. string DayOfWeek,
  20. string Name
  21. )> Data { get; private set; } = [];
  22. [BindProperty]
  23. public InputModel Input { get; set; } = new();
  24. public sealed class InputModel
  25. {
  26. [Required]
  27. public DateOnly? Date { get; set; }
  28. [Required]
  29. [StringLength(50)]
  30. public string? Name { get; set; }
  31. }
  32. [BindProperty]
  33. public DateOnly DeleteDate { get; set; }
  34. public async Task OnGetAsync(int? year, CancellationToken ct)
  35. {
  36. Year = year;
  37. var result = await mediator.Send(new GetMarketHolidays.Query(year), ct);
  38. Total = result.Total;
  39. Years = [..result.Years];
  40. Data = [..result.List.Select(c => (
  41. c.Date,
  42. CultureInfo.GetCultureInfo("ko-KR").DateTimeFormat.GetDayName(c.Date.DayOfWeek),
  43. c.Name
  44. ))];
  45. }
  46. public async Task<IActionResult> OnPostAddAsync(int? year, CancellationToken ct)
  47. {
  48. if (!ModelState.IsValid || Input.Date is null || Input.Name is null)
  49. {
  50. TempData["ErrorMessages"] = ModelState.GetErrorMessages();
  51. return RedirectToIndex(year);
  52. }
  53. var result = await mediator.Send(new AddMarketHoliday.Command(Input.Date.Value, Input.Name), ct);
  54. if (result.IsFailure)
  55. {
  56. TempData["ErrorMessages"] = result.Error.Description;
  57. }
  58. else
  59. {
  60. TempData["SuccessMessage"] = $"{Input.Date.Value:yyyy-MM-dd} ({Input.Name}) 휴장일이 등록되었습니다.";
  61. }
  62. return RedirectToIndex(year);
  63. }
  64. public async Task<IActionResult> OnPostDeleteAsync(int? year, CancellationToken ct)
  65. {
  66. var result = await mediator.Send(new DeleteMarketHoliday.Command(DeleteDate), ct);
  67. if (result.IsFailure)
  68. {
  69. TempData["ErrorMessages"] = result.Error.Description;
  70. }
  71. else
  72. {
  73. TempData["SuccessMessage"] = $"{DeleteDate:yyyy-MM-dd} 휴장일이 삭제되었습니다.";
  74. }
  75. return RedirectToIndex(year);
  76. }
  77. private RedirectToPageResult RedirectToIndex(int? year)
  78. {
  79. return year.HasValue ? RedirectToPage("/Stocks/MarketHoliday/Index", new { year }) : RedirectToPage("/Stocks/MarketHoliday/Index");
  80. }
  81. }