Handler.cs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. using Application.Abstractions.Data;
  2. using Application.Abstractions.Messaging;
  3. using Microsoft.EntityFrameworkCore;
  4. using SharedKernel.Results;
  5. namespace Application.Features.Api.Stocks.GetBondDetail;
  6. internal sealed class Handler(IAppDbContext db) : IQueryHandler<Query, Result<Response>>
  7. {
  8. public async Task<Result<Response>> Handle(Query request, CancellationToken ct)
  9. {
  10. var isin = request.Isin?.Trim();
  11. if (string.IsNullOrEmpty(isin))
  12. {
  13. return Result.Failure<Response>(Error.Problem("Bond.IsinRequired", "채권 종목코드(ISIN)가 필요합니다."));
  14. }
  15. var master = await db.BondMaster.AsNoTracking().Where(c => c.Isin == isin).FirstOrDefaultAsync(ct);
  16. var interest = await db.BondInterestPayment.AsNoTracking().Where(c => c.Isin == isin).FirstOrDefaultAsync(ct);
  17. // KRX 일별매매(BondDailyTrade)는 (BondMarket, Code, TradeDate) 라 ISIN(Code) 최신 거래일 1행
  18. var market = await db.BondDailyTrade.AsNoTracking()
  19. .Where(c => c.Code == isin)
  20. .OrderByDescending(c => c.TradeDate)
  21. .FirstOrDefaultAsync(ct);
  22. if (master is null && interest is null && market is null)
  23. {
  24. return Result.Failure<Response>(Error.NotFound("Bond.NotFound", "해당 채권 정보를 찾을 수 없습니다."));
  25. }
  26. return new Response
  27. {
  28. Isin = isin,
  29. Master = master is null ? null : new Response.MasterInfo
  30. {
  31. Name = master.KorSecnNm,
  32. IssucoCustno = master.IssucoCustno,
  33. SecnKacd = master.SecnKacd,
  34. IssueDate = master.IssuDt,
  35. MaturityDate = master.XpirDt,
  36. Currency = master.IssuCurCd,
  37. FirstIssueAmount = master.FirstIssuAmt,
  38. IssueRemaining = master.IssuRema,
  39. CouponRate = master.CouponRate,
  40. OptionTpcd = master.OptionTpcd,
  41. ForcedEarlyRedemption = master.ForcErlyRedYn,
  42. RateChangeTpcd = master.MrChgTpcd,
  43. GuaranteeTpcd = master.GrtyTpcd,
  44. RankTpcd = master.RankTpcd,
  45. IntPayWayTpcd = master.IntPayWayTpcd,
  46. ParticularBondKindTpcd = master.ParticulBondKindTpcd,
  47. KisGrade = master.KisValatGrdCd,
  48. NiceGrade = master.NiceValatGrdCd,
  49. SciGrade = master.SciValatGrdCd,
  50. KrGrade = master.KrValatGrdCd,
  51. IsElectronicSecurity = master.EltscYn
  52. },
  53. Interest = interest is null ? null : new Response.InterestInfo
  54. {
  55. CouponRate = interest.CouponRate,
  56. IntPayWayTpcd = interest.IntPayWayTpcd,
  57. CycleTerms = interest.IntPayCycleTerms,
  58. CycleTpcd = interest.IntPayCycleTpcd,
  59. PayTimingTpcd = interest.IntPayTimsTpcd,
  60. BeforeCouponDate = interest.BeforeDate,
  61. AfterCouponDate = interest.AfterDate
  62. },
  63. Market = market is null ? null : new Response.MarketInfo
  64. {
  65. TradeDate = market.TradeDate,
  66. Close = market.Close,
  67. YieldToMaturity = market.YieldToMaturity,
  68. Volume = market.Volume
  69. }
  70. };
  71. }
  72. }