Index.cshtml 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. @page
  2. @using Domain.Entities.Developers.ValueObject
  3. @model Admin.Pages.Developers.Purchases.IndexModel
  4. @{
  5. ViewData["Title"] = "결제 보고 내역";
  6. static string MarketLabel(ApiPurchaseMarketplace m) => m switch
  7. {
  8. ApiPurchaseMarketplace.GooglePlay => "구글",
  9. ApiPurchaseMarketplace.AppStore => "애플",
  10. ApiPurchaseMarketplace.Microsoft => "MS",
  11. ApiPurchaseMarketplace.GalaxyStore => "갤럭시",
  12. ApiPurchaseMarketplace.OneStore => "원스토어",
  13. _ => "기타"
  14. };
  15. }
  16. <div class="container-fluid">
  17. <h3>@ViewData["Title"]</h3>
  18. <hr />
  19. <partial name="_StatusMessage" />
  20. <form id="fAdminSearch" method="get">
  21. <div class="row g-2 align-items-end">
  22. <div class="col-6 col-sm-auto">
  23. <select name="status" id="status" class="form-select">
  24. <option value="">상태 전체</option>
  25. <option value="@((int)ApiPurchaseStatus.Pending)" selected="@(Model.Query.Status == ApiPurchaseStatus.Pending)">보류</option>
  26. <option value="@((int)ApiPurchaseStatus.Confirmed)" selected="@(Model.Query.Status == ApiPurchaseStatus.Confirmed)">확정</option>
  27. <option value="@((int)ApiPurchaseStatus.Canceled)" selected="@(Model.Query.Status == ApiPurchaseStatus.Canceled)">취소</option>
  28. </select>
  29. </div>
  30. <div class="col-6 col-sm-auto">
  31. <input type="date" name="from" class="form-control" value="@(Model.Query.From?.ToString("yyyy-MM-dd"))" />
  32. </div>
  33. <div class="col-6 col-sm-auto">
  34. <input type="date" name="to" class="form-control" value="@(Model.Query.To?.ToString("yyyy-MM-dd"))" />
  35. </div>
  36. <div class="col-12 col-sm col-md col-lg-auto">
  37. <input type="text" name="keyword" class="form-control" maxlength="255" value="@Model.Query.Keyword" placeholder="orderID/후원코드/게임코드/채널명" />
  38. </div>
  39. <div class="col-auto">
  40. <div class="form-check">
  41. <input type="checkbox" name="onlyMismatch" id="onlyMismatch" value="true" class="form-check-input" checked="@Model.Query.OnlyMismatch" />
  42. <label for="onlyMismatch" class="form-check-label">금액 불일치만</label>
  43. </div>
  44. </div>
  45. <div class="col-12 col-lg-auto">
  46. <button type="submit" class="btn btn-primary">검색</button>
  47. </div>
  48. </div>
  49. </form>
  50. <hr />
  51. @if (Model.Summary != null)
  52. {
  53. <div class="row g-2 mb-3">
  54. <div class="col-auto"><span class="badge bg-light text-dark border">보고액 합계 @Model.Summary.TotalOrderPrice.ToString("N0")원</span></div>
  55. <div class="col-auto"><span class="badge bg-light text-dark border">수수료 합계 @Model.Summary.TotalCommission.ToString("N0")원</span></div>
  56. <div class="col-auto"><span class="badge bg-secondary">보류 @Model.Summary.PendingCount.ToString("N0")</span></div>
  57. <div class="col-auto"><span class="badge bg-success">확정 @Model.Summary.ConfirmedCount.ToString("N0")</span></div>
  58. <div class="col-auto"><span class="badge bg-dark">취소 @Model.Summary.CanceledCount.ToString("N0")</span></div>
  59. @if (Model.Summary.MismatchCount > 0)
  60. {
  61. <div class="col-auto"><span class="badge bg-danger">금액 불일치 @Model.Summary.MismatchCount.ToString("N0")</span></div>
  62. }
  63. @if (Model.Summary.TotalShortfall > 0)
  64. {
  65. <div class="col-auto"><span class="badge bg-warning text-dark">미회수 @Model.Summary.TotalShortfall.ToString("N0")원</span></div>
  66. }
  67. </div>
  68. }
  69. <div class="row g-2 align-items-end mb-2">
  70. <div class="col">Total: @Model.Total.ToString("N0")</div>
  71. </div>
  72. <div class="table-responsive">
  73. <table class="table table-bordered table-hover">
  74. <thead>
  75. <tr>
  76. <th>ID</th>
  77. <th>등록일</th>
  78. <th>앱</th>
  79. <th>게임</th>
  80. <th>채널 (후원코드)</th>
  81. <th>마켓</th>
  82. <th>orderID</th>
  83. <th>SKU</th>
  84. <th class="text-end">보고액</th>
  85. <th class="text-end">수수료 (율)</th>
  86. <th>상태</th>
  87. <th>확정 예정/일시</th>
  88. </tr>
  89. </thead>
  90. <tbody>
  91. @if (Model.List.Count <= 0)
  92. {
  93. <tr>
  94. <td colspan="12" class="text-center text-muted py-4">No Data.</td>
  95. </tr>
  96. }
  97. else
  98. {
  99. @foreach (var row in Model.List)
  100. {
  101. <tr>
  102. <td>@row.ID</td>
  103. <td>@row.CreatedAt.ToString("yyyy-MM-dd HH:mm")</td>
  104. <td>@row.AppName</td>
  105. <td>@row.GameName</td>
  106. <td>@row.ChannelName (@(row.ChannelCode ?? "-"))</td>
  107. <td>@MarketLabel(row.Marketplace)</td>
  108. <td><code>@row.OrderID</code></td>
  109. <td>
  110. @(row.ProductID ?? "-")
  111. @if (row.PriceMismatched)
  112. {
  113. <span class="badge bg-danger" title="카탈로그 정가 @(row.CatalogPrice?.ToString("N0") ?? "-")원과 불일치">불일치</span>
  114. }
  115. </td>
  116. <td class="text-end">@row.OrderPrice.ToString("N0")원</td>
  117. <td class="text-end">@row.CommissionAmount.ToString("N0")원 (@row.CommissionRate%)</td>
  118. <td>
  119. @switch (row.Status)
  120. {
  121. case ApiPurchaseStatus.Pending:
  122. <span class="badge bg-secondary">보류</span>
  123. break;
  124. case ApiPurchaseStatus.Confirmed:
  125. <span class="badge bg-success">확정</span>
  126. break;
  127. case ApiPurchaseStatus.Canceled:
  128. <span class="badge bg-dark">취소</span>
  129. if (row.CancelWasConfirmed == true)
  130. {
  131. <small class="text-muted d-block">회수 @(row.RecoveredAmount?.ToString("N0") ?? "0")원</small>
  132. }
  133. if (row.ShortfallAmount > 0)
  134. {
  135. <span class="badge bg-warning text-dark">미회수 @(row.ShortfallAmount?.ToString("N0"))원</span>
  136. }
  137. break;
  138. }
  139. </td>
  140. <td>
  141. @if (row.Status == ApiPurchaseStatus.Pending)
  142. {
  143. @row.ConfirmDueAt.ToString("yyyy-MM-dd")
  144. <small class="text-muted">예정</small>
  145. }
  146. else if (row.ConfirmedAt != null)
  147. {
  148. @row.ConfirmedAt.Value.ToString("yyyy-MM-dd HH:mm")
  149. }
  150. else if (row.CanceledAt != null)
  151. {
  152. <small class="text-muted">@row.CanceledAt.Value.ToString("yyyy-MM-dd HH:mm") 취소</small>
  153. }
  154. </td>
  155. </tr>
  156. }
  157. }
  158. </tbody>
  159. </table>
  160. </div>
  161. @if (Model.Pagination != null)
  162. {
  163. <partial name="_Pagination" model="Model.Pagination" />
  164. }
  165. </div>