using MediatR; using Web.Api.Common; using Web.Api.Extensions; namespace Web.Api.Endpoints.V1.Coupons; internal sealed class ListByGame : IEndpoint { public void MapEndpoint(IEndpointRouteBuilder app) { app.MapGet("v1/games/{gameID:int}/coupons", async ( int gameID, ISender sender, CancellationToken ct, int? couponID = null, int page = 1, int limit = 100 ) => { var query = new Application.Features.Api.V1.Coupons.ListByGame.Query(gameID, couponID, page, limit); var result = await sender.Send(query, ct); return result.Match( data => ApiResponse.Ok(data), CustomResults.Problem ); }) .WithTags("쿠폰") .WithGroupName("public") .WithName("ListGameCoupons") .WithSummary("게임 쿠폰 코드 대량 조회") .WithDescription(""" 특정 게임에 발급된 **쿠폰 코드를 대량으로** 페이지네이션해 반환합니다. 각 코드의 사용 여부(`status`) + 발급/사용 일시가 함께 제공됩니다. ### 필수 scope - `read:coupons` ### 경로 변수 - `gameID` — 게임 ID ### 쿼리 파라미터 | 이름 | 타입 | 기본 | 설명 | |---|---|---|---| | `couponID` | int? | null | 특정 쿠폰의 코드만 필터 (생략 시 게임 전체) | | `page` | int | 1 | 1부터 시작 | | `limit` | int | 100 | 1~500 | ### Status 값 | 값 | 의미 | |---|---| | `1` | Available (미발급) | | `2` | Reserved (결제 진행 중) | | `3` | Issued (발급됨) | | `4` | Used (사용 완료) | | `5` | Expired (만료) | """) .Produces(StatusCodes.Status200OK) .ProducesProblem(StatusCodes.Status400BadRequest) .ProducesProblem(StatusCodes.Status401Unauthorized) .ProducesProblem(StatusCodes.Status403Forbidden) .ProducesProblem(StatusCodes.Status404NotFound) .RequireAuthorization(policy => policy .AddAuthenticationSchemes("ApiKey", "OAuth2Bearer") .RequireAuthenticatedUser()) .RequireScope("read:coupons"); } }