namespace Infrastructure.StockData; /// /// SEIBro getDivSchedulInfo(배당일정) 응답 파서 — 순수 C#. 공용 SeibroXml envelope 입력. /// 자연키(ISSUCO_CUSTNO, RGT_STD_DT, RGT_RSN_DTAIL_SORT_CD) 중 하나라도 없거나 회사번호 비숫자·기준일 비형식이면 건너뛴다. /// 날짜 필드는 YYYYMMDD→DateOnly (빈값 null), ELTSC_YN 은 Y/N→bool (그 외 null). /// public static class SeibroDivSchedulParser { public sealed record Row( int IssucoCustno, string RepSecnNm, string? RgtRacd, string RgtRsnDetailSortCd, DateOnly RgtStdDt, string? AllocWhcd, string? SetaccTpcd, string? FixTpcd, DateOnly? RostCloseBeginDt, DateOnly? RostCloseExpryDt, DateOnly? XrgtDt, bool? IsElectronicSecurity ); public static IReadOnlyList Parse(SeibroXml.Envelope envelope) { var rows = new List(); foreach (var fields in envelope.Rows) { var custno = SeibroFieldParse.Int(SeibroXml.GetOrNull(fields, "ISSUCO_CUSTNO")); var repSecnNm = SeibroXml.GetOrNull(fields, "REP_SECN_NM")?.Trim(); var sortCd = SeibroXml.GetOrNull(fields, "RGT_RSN_DTAIL_SORT_CD")?.Trim(); var rgtStdDt = SeibroFieldParse.Date(SeibroXml.GetOrNull(fields, "RGT_STD_DT")); if (custno is null || string.IsNullOrEmpty(repSecnNm) || string.IsNullOrEmpty(sortCd) || rgtStdDt is null) { continue; } rows.Add(new Row( custno.Value, repSecnNm, SeibroXml.GetOrNull(fields, "RGT_RACD")?.Trim(), sortCd, rgtStdDt.Value, SeibroXml.GetOrNull(fields, "ALOC_WHCD")?.Trim(), SeibroXml.GetOrNull(fields, "SETACC_TPCD")?.Trim(), SeibroXml.GetOrNull(fields, "FIX_TPCD")?.Trim(), SeibroFieldParse.Date(SeibroXml.GetOrNull(fields, "ROST_CLOSE_BEGIN_DT")), SeibroFieldParse.Date(SeibroXml.GetOrNull(fields, "ROST_CLOSE_EXPRY_DT")), SeibroFieldParse.Date(SeibroXml.GetOrNull(fields, "XRGT_DT")), SeibroFieldParse.Yn(SeibroXml.GetOrNull(fields, "ELTSC_YN")) )); } return rows; } }