using System.Security.Claims; using System.Text.Json.Serialization; using Application.Abstractions.Messaging; using Domain.Entities.Paper.ValueObject; using SharedKernel.Results; using Web.Api.Common; using Web.Api.Extensions; namespace Web.Api.Endpoints.Paper; public sealed class PlaceOrderRequest { [JsonPropertyName("stockCode")] public string StockCode { get; set; } = ""; /// 주문 방향 — "Buy" | "Sell" (대소문자 무시). [JsonPropertyName("side")] public string Side { get; set; } = ""; [JsonPropertyName("quantity")] public int Quantity { get; set; } } /// 모의투자 — 주문 접수. internal sealed class PlaceOrder : IEndpoint { public void MapEndpoint(IEndpointRouteBuilder app) { app.MapPost("api/paper/orders", async ( PlaceOrderRequest body, ClaimsPrincipal user, ISender sender, CancellationToken ct ) => { if (!Enum.TryParse(body.Side, ignoreCase: true, out var side) || !Enum.IsDefined(side)) { return CustomResults.Problem(Result.Failure(Error.Problem("Paper.InvalidSide", "주문 방향(side)이 올바르지 않습니다. (Buy | Sell)"))); } var memberID = user.GetRequiredMemberID(); var result = await sender.Send(new Application.Features.Api.Paper.PlaceOrder.Command(memberID, body.StockCode, side, body.Quantity), ct); if (result.IsFailure) { return CustomResults.Problem(result); } return ApiResponse.Ok(result.Value); }) .WithTags("Paper") .RequireAuthorization(); } }