Handler.cs 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. using Application.Abstractions.Data;
  2. using Application.Abstractions.Messaging;
  3. using Domain.Entities.Developers.ValueObject;
  4. using Microsoft.EntityFrameworkCore;
  5. using SharedKernel.Results;
  6. namespace Application.Features.Api.V1.Purchases.Get;
  7. internal sealed class Handler(IAppDbContext db) : IQueryHandler<Query, Result<Response>>
  8. {
  9. public async Task<Result<Response>> Handle(Query request, CancellationToken ct)
  10. {
  11. if (string.IsNullOrWhiteSpace(request.OrderID))
  12. {
  13. return Result.Failure<Response>(Error.Problem("Purchase.OrderIDRequired", "orderID 는 필수입니다."));
  14. }
  15. if (request.Marketplace.HasValue && !Enum.IsDefined(typeof(ApiPurchaseMarketplace), request.Marketplace.Value))
  16. {
  17. return Result.Failure<Response>(Error.Problem("Purchase.MarketplaceInvalid", "marketplace 는 1(구글)~6(기타) 값이어야 합니다."));
  18. }
  19. var orderID = request.OrderID.Trim();
  20. var query = db.ApiPurchase.AsNoTracking().Where(c => c.OrderID == orderID);
  21. // 호출 주체 범위 제한 — OAuth2: 해당 앱 / PAT: 본인 소유 앱 전체
  22. if (request.ApplicationID.HasValue)
  23. {
  24. query = query.Where(c => c.ApplicationID == request.ApplicationID.Value);
  25. }
  26. else if (request.OwnerMemberID.HasValue)
  27. {
  28. query = query.Where(c => c.Application!.OwnerMemberID == request.OwnerMemberID.Value);
  29. }
  30. else
  31. {
  32. return Result.Failure<Response>(Error.Unauthorized("Purchase.CallerUnknown", "호출 주체를 식별할 수 없습니다."));
  33. }
  34. if (request.Marketplace.HasValue)
  35. {
  36. var marketplace = (ApiPurchaseMarketplace)request.Marketplace.Value;
  37. query = query.Where(c => c.Marketplace == marketplace);
  38. }
  39. var rows = await query
  40. .Select(c => new Response(
  41. c.ID,
  42. c.OrderID,
  43. (int)c.Marketplace,
  44. c.Channel!.DonationCode,
  45. c.Channel!.SID,
  46. c.Game!.Code ?? string.Empty,
  47. c.ProductID,
  48. c.SubID,
  49. c.OrderPrice,
  50. c.CommissionRate,
  51. c.CommissionAmount,
  52. c.Status.ToString(),
  53. c.ConfirmDueAt,
  54. c.ConfirmedAt,
  55. c.CanceledAt,
  56. c.CreatedAt
  57. ))
  58. .ToListAsync(ct);
  59. if (rows.Count == 0)
  60. {
  61. return Result.Failure<Response>(Error.NotFound("Purchase.NotFound", "등록된 주문을 찾을 수 없습니다."));
  62. }
  63. if (rows.Count > 1)
  64. {
  65. return Result.Failure<Response>(Error.Problem("Purchase.AmbiguousOrderID", "여러 건이 조회되었습니다. marketplace 를 지정하세요."));
  66. }
  67. return Result.Success(rows[0]);
  68. }
  69. }