namespace Infrastructure.StockData; /// /// SEIBro getStkIncdecDetails(주식증감내역) 응답 파서 — 순수 C#. 공용 SeibroXml envelope 입력. /// 자연키(ISIN, SECN_ISSU_NTIMES, ISSU_DT, SECN_ISSU_RACD) 중 하나라도 없거나 비형식인 행은 건너뛴다. /// ISSU_QTY 는 감소(소각) 시 음수 → Long 이 부호 보존. ISSUPRC 0 은 유효값(무상). /// public static class SeibroStkIncdecParser { public sealed record Row( int? IssucoCustno, string Isin, string? SecnKacd, int SecnIssuNtimes, DateOnly IssuDt, decimal? Issuprc, long? IssuQty, string SecnIssuRacd, string? SecnIssuNm, DateOnly? ListDt ); public static IReadOnlyList Parse(SeibroXml.Envelope envelope) { var rows = new List(); foreach (var fields in envelope.Rows) { var isin = SeibroXml.GetOrNull(fields, "ISIN")?.Trim(); var ntimes = SeibroFieldParse.Int(SeibroXml.GetOrNull(fields, "SECN_ISSU_NTIMES")); var issuDt = SeibroFieldParse.Date(SeibroXml.GetOrNull(fields, "ISSU_DT")); var racd = SeibroXml.GetOrNull(fields, "SECN_ISSU_RACD")?.Trim(); if (string.IsNullOrEmpty(isin) || ntimes is null || issuDt is null || string.IsNullOrEmpty(racd)) { continue; } rows.Add(new Row( SeibroFieldParse.Int(SeibroXml.GetOrNull(fields, "ISSUCO_CUSTNO")), isin, SeibroXml.GetOrNull(fields, "SECN_KACD")?.Trim(), ntimes.Value, issuDt.Value, SeibroFieldParse.Decimal(SeibroXml.GetOrNull(fields, "ISSUPRC")), SeibroFieldParse.Long(SeibroXml.GetOrNull(fields, "ISSU_QTY")), racd, SeibroXml.GetOrNull(fields, "SECN_ISSU_NM")?.Trim(), SeibroFieldParse.Date(SeibroXml.GetOrNull(fields, "LIST_DT")) )); } return rows; } }