ProductSales.cs 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. using MediatR;
  2. using Web.Api.Common;
  3. using Web.Api.Extensions;
  4. namespace Web.Api.Endpoints.V1.Stats;
  5. internal sealed class ProductSales : IEndpoint
  6. {
  7. public void MapEndpoint(IEndpointRouteBuilder app)
  8. {
  9. app.MapGet("v1/stats/products", async (
  10. ISender sender,
  11. CancellationToken ct,
  12. int gameID = 0
  13. ) => {
  14. var query = new Application.Features.Api.V1.Stats.ProductSales.Query(gameID);
  15. var result = await sender.Send(query, ct);
  16. return result.Match(
  17. data => ApiResponse.Ok(data),
  18. CustomResults.Problem
  19. );
  20. })
  21. .WithTags("통계")
  22. .WithGroupName("public")
  23. .WithName("GetProductSalesStats")
  24. .WithSummary("상품 판매 통계 (게임사별)")
  25. .WithDescription("""
  26. 특정 게임사의 **모든 상품별 판매 통계**를 반환합니다.
  27. ### 포함 수치 (상품 별)
  28. | 필드 | 의미 |
  29. |---|---|
  30. | `soldQuantity` | 누적 판매 수량 (Pending/Cancelled/Refunded 제외) |
  31. | `salesAmount` | 누적 판매 금액 (단가 × 수량) |
  32. | `couponGeneratedCount` | 발급된 총 쿠폰 코드 수 (쿠폰 상품만) |
  33. | `couponIssuedCount` | 회원 보관함에 발급된 코드 수 (Status=Issued) |
  34. | `couponUsedCount` | 사용 완료된 코드 수 (Status=Used) |
  35. | `couponAvailableCount` | 미사용 / 미발급 코드 수 (Status=Available) |
  36. ### 필수 scope
  37. - `read:stats`
  38. ### 쿼리 파라미터
  39. - `gameID` (필수) — 게임 ID
  40. ### 에러
  41. - `400` — gameID 누락
  42. - `404` — 해당 게임 없음
  43. """)
  44. .Produces<ApiResponse>(StatusCodes.Status200OK)
  45. .ProducesProblem(StatusCodes.Status400BadRequest)
  46. .ProducesProblem(StatusCodes.Status401Unauthorized)
  47. .ProducesProblem(StatusCodes.Status403Forbidden)
  48. .ProducesProblem(StatusCodes.Status404NotFound)
  49. .RequireAuthorization(policy => policy
  50. .AddAuthenticationSchemes("ApiKey", "OAuth2Bearer")
  51. .RequireAuthenticatedUser())
  52. .RequireScope("read:stats");
  53. }
  54. }