namespace Infrastructure.StockData; /// /// SEIBro getCDInfo(CD 종목 정보) 응답 파서 — 순수 C#. 공용 SeibroXml envelope 입력. /// ⚠️ 실샘플 fixture 가 result="0"(빈) 이라 필드 매핑은 채권.md 스펙 기준 — 운영 첫 수집 시 로그로 확인. /// ⚠️ 응답에 ISIN 필드가 없다(요청 파라미터로만 받음) — Isin 은 배치가 요청값을 스탬핑하므로 여기선 필드 묶음만 반환. /// 종목당 1행이라 첫 행만 의미가 있으나 방어적으로 전 행 반환. Y/N→bool, 날짜→DateOnly, 숫자→decimal/int. /// public static class SeibroCDParser { public sealed record Row( int? IssucoCustno, string? KorSecnNm, string? IssuCurCd, decimal? FirstIssuAmt, string? IssuWhcd, decimal? FaceAmt, decimal? SaleAmt, decimal? DiscnRate, string? IntPayMannTpcd, DateOnly? IssuDt, DateOnly? XpirDt, bool? EltscYn ); public static IReadOnlyList Parse(SeibroXml.Envelope envelope) { var rows = new List(); foreach (var fields in envelope.Rows) { rows.Add(new Row( SeibroFieldParse.Int(SeibroXml.GetOrNull(fields, "ISSUCO_CUSTNO")), SeibroXml.GetOrNull(fields, "KOR_SECN_NM")?.Trim(), SeibroXml.GetOrNull(fields, "ISSU_CUR_CD")?.Trim(), SeibroFieldParse.Decimal(SeibroXml.GetOrNull(fields, "FIRST_ISSU_AMT")), SeibroXml.GetOrNull(fields, "ISSU_WHCD")?.Trim(), SeibroFieldParse.Decimal(SeibroXml.GetOrNull(fields, "FACE_AMT")), SeibroFieldParse.Decimal(SeibroXml.GetOrNull(fields, "SALE_AMT")), SeibroFieldParse.Decimal(SeibroXml.GetOrNull(fields, "DISCN_RATE")), SeibroXml.GetOrNull(fields, "INT_PAY_MANN_TPCD")?.Trim(), SeibroFieldParse.Date(SeibroXml.GetOrNull(fields, "ISSU_DT")), SeibroFieldParse.Date(SeibroXml.GetOrNull(fields, "XPIR_DT")), SeibroFieldParse.Yn(SeibroXml.GetOrNull(fields, "ELTSC_YN")) )); } return rows; } }