using System.ComponentModel.DataAnnotations;
namespace Domain.Entities.Stocks;
///
/// SEIBro 종목별 외화증권 결제현황 (getSecnFrsecSetlInfo) — KSD 를 통한 특정 외화종목(ISIN)의 매수/매도 결제신청수량·금액(USD) (Wave 6). 자연키 UNIQUE (ProcDt, Isin, IntlBizCacd).
/// 응답 필드는 NationCd·SecnTpcd·IntlBizCacd·SetlAskQty·SetlAmt 5종 — 배치가 PROC_DT·ISIN 을 요청값으로 스탬핑한다.
/// PROC_DT = 결제처리일(한국시간) — 미국시간 T일 결제는 처리일 T+1 반영. IntlBizCacd = 1110매수/1120매도. ForeignIsins 기본 빈 리스트라 사실상 대기.
///
public class ForeignSettlementSecurity
{
[Key]
public int ID { get; private set; }
/// 결제처리일 (PROC_DT, 요청값 스탬핑, 한국시간)
public DateOnly ProcDt { get; private set; }
/// 종목코드 (ISIN, 요청값 스탬핑)
public string Isin { get; private set; } = default!;
/// 국제업무분류코드 (INTL_BIZ_CACD) — 1110매수 1120매도
public string IntlBizCacd { get; private set; } = default!;
/// 국가코드 (NATION_CD)
public string? NationCd { get; private set; }
/// 종목구분코드 (SECN_TPCD) — 71외화주식~78외화수익증권
public string? SecnTpcd { get; private set; }
/// 결제신청수량 (SETL_ASK_QTY) — 주식:주, 채권:액면금액
public decimal? SetlAskQty { get; private set; }
/// 결제금액 (SETL_AMT) — USD
public decimal? SetlAmt { get; private set; }
public DateTime UpdatedAt { get; private set; } = DateTime.UtcNow;
private ForeignSettlementSecurity() { }
public static ForeignSettlementSecurity Create(DateOnly procDt, string isin, string intlBizCacd, string? nationCd, string? secnTpcd, decimal? setlAskQty, decimal? setlAmt)
{
if (string.IsNullOrWhiteSpace(isin))
{
throw new ArgumentException("isin required", nameof(isin));
}
if (string.IsNullOrWhiteSpace(intlBizCacd))
{
throw new ArgumentException("intlBizCacd required", nameof(intlBizCacd));
}
return new ForeignSettlementSecurity
{
ProcDt = procDt,
Isin = isin.Trim(),
IntlBizCacd = intlBizCacd.Trim(),
NationCd = Trimmed(nationCd),
SecnTpcd = Trimmed(secnTpcd),
SetlAskQty = setlAskQty,
SetlAmt = setlAmt
};
}
/// 재수집 반영 — 변경 필드가 있을 때만 UpdatedAt 갱신 (자연키 ProcDt/Isin/IntlBizCacd 은 불변)
public void Update(string? nationCd, string? secnTpcd, decimal? setlAskQty, decimal? setlAmt)
{
var changed = false;
changed |= Set(Trimmed(nationCd), NationCd, v => NationCd = v);
changed |= Set(Trimmed(secnTpcd), SecnTpcd, v => SecnTpcd = v);
changed |= Set(setlAskQty, SetlAskQty, v => SetlAskQty = v);
changed |= Set(setlAmt, SetlAmt, v => SetlAmt = v);
if (changed)
{
UpdatedAt = DateTime.UtcNow;
}
}
private static string? Trimmed(string? value)
{
return string.IsNullOrWhiteSpace(value) ? null : value.Trim();
}
private static bool Set(T incoming, T current, Action assign)
{
if (EqualityComparer.Default.Equals(incoming, current))
{
return false;
}
assign(incoming);
return true;
}
}