Export.cshtml.cs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. using System.ComponentModel;
  2. using System.ComponentModel.DataAnnotations;
  3. using System.Text;
  4. using Domain.Entities.Store.ValueObject;
  5. using Application.Abstractions.Messaging;
  6. using Microsoft.AspNetCore.Mvc;
  7. using Microsoft.AspNetCore.Mvc.RazorPages;
  8. namespace Admin.Pages.Store.Settlement;
  9. /// <summary>
  10. /// 게임사 정산 목록 CSV 다운로드. 현재 필터 기준 최대 10,000 row 익스포트.
  11. /// </summary>
  12. public class ExportModel(IMediator mediator) : PageModel
  13. {
  14. [BindProperty(SupportsGet = true)]
  15. public QueryParams Query { get; set; } = new();
  16. public sealed class QueryParams
  17. {
  18. [DisplayName("게임")]
  19. public int? GameID { get; set; }
  20. [DisplayName("연도")]
  21. [Range(2000, 9999)]
  22. public int? Year { get; set; }
  23. [DisplayName("월")]
  24. [Range(1, 12)]
  25. public int? Month { get; set; }
  26. [DisplayName("정산 상태")]
  27. public GameSettlementStatus? Status { get; set; }
  28. }
  29. public async Task<IActionResult> OnGetAsync(CancellationToken ct)
  30. {
  31. // 한 번에 최대 10,000 row 익스포트 (운영상 충분)
  32. var result = await mediator.Send(new SearchGameSettlements.Query(
  33. Query.GameID,
  34. Query.Year,
  35. Query.Month,
  36. Query.Status,
  37. 1,
  38. 10000
  39. ), ct);
  40. var sb = new StringBuilder();
  41. sb.Append(''); // UTF-8 BOM (Excel 한글 호환)
  42. sb.AppendLine("게임ID,게임명,게임사,연도,월,매출(원),주문수,상태,등록일시,처리일시,처리관리자,관리자메모");
  43. foreach (var c in result.List)
  44. {
  45. sb.Append(c.GameID).Append(',');
  46. sb.Append(Csv(c.GameName)).Append(',');
  47. sb.Append(Csv(c.GamePublisher)).Append(',');
  48. sb.Append(c.Year).Append(',');
  49. sb.Append(c.Month).Append(',');
  50. sb.Append(c.TotalRevenueAmount).Append(',');
  51. sb.Append(c.OrderCount).Append(',');
  52. sb.Append(Csv(StatusToText(c.Status))).Append(',');
  53. sb.Append(c.CreatedAt.ToString("yyyy-MM-dd HH:mm")).Append(',');
  54. sb.Append(c.SettledAt?.ToString("yyyy-MM-dd HH:mm") ?? "").Append(',');
  55. sb.Append(Csv(c.SettledByAdminEmail ?? "")).Append(',');
  56. sb.AppendLine(Csv(c.AdminMemo ?? ""));
  57. }
  58. var fileName = $"GameSettlements_{DateTime.UtcNow:yyyyMMdd_HHmmss}.csv";
  59. return File(Encoding.UTF8.GetBytes(sb.ToString()), "text/csv", fileName);
  60. }
  61. private static string Csv(string s)
  62. {
  63. if (string.IsNullOrEmpty(s))
  64. {
  65. return "";
  66. }
  67. if (s.Contains(',') || s.Contains('"') || s.Contains('\n') || s.Contains('\r'))
  68. {
  69. return "\"" + s.Replace("\"", "\"\"") + "\"";
  70. }
  71. return s;
  72. }
  73. private static string StatusToText(GameSettlementStatus s) => s switch
  74. {
  75. GameSettlementStatus.Pending => "정산 대기",
  76. GameSettlementStatus.Settled => "정산 완료",
  77. _ => "?"
  78. };
  79. }