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;
}
}