using System.ComponentModel.DataAnnotations; namespace Domain.Entities.Stocks; /// /// SEIBro 기초자산별 미상환규모 (getBassetUnredScale) — 주요 기초자산(13종)별 미상환종목수·미상환잔액 (Wave 5, ★P2). /// **ELS 지수 하락 리스크 지표** (개미 관심). 자연키 UNIQUE (StdDt, StndBassetCd, SecnTpcd). /// 일별 13기초자산 × SECN_TPCD{41ELS/43DLS} = 최대 26콜/일 스윕. 응답 필드는 BassetContent·UnredSecncnt·UnredRema 3종. /// ⚠️ 응답에 없는 StdDt·StndBassetCd·SecnTpcd 는 요청 파라미터를 배치가 스탬핑한다. /// ⚠️ StndBassetCd 는 입력 13종(KSD02*) 원문 — getAssetInfo 반환 코드체계(KSD31*)와 달라 매핑 흡수하지 않고 원문 저장. /// public class ElsUnredeemedScale { [Key] public int ID { get; private set; } /// 기준일자 (STD_DT, 요청값 스탬핑) public DateOnly StdDt { get; private set; } /// 표준기초자산코드 (STND_BASSET_CD, 요청값 스탬핑) — 입력 13종 KSD02* 원문 public string StndBassetCd { get; private set; } = default!; /// 종목구분코드 (SECN_TPCD, 요청값 스탬핑) — 41ELS 43DLS public string SecnTpcd { get; private set; } = default!; /// 기초자산내용 (BASSET_CONTENT) — 예 EURO STOXX 50 public string? BassetContent { get; private set; } /// 미상환종목수 (UNRED_SECNCNT) public int? UnredSecncnt { get; private set; } /// 미상환잔액 (UNRED_REMA) — 원화 환산 합계 public decimal? UnredRema { get; private set; } public DateTime UpdatedAt { get; private set; } = DateTime.UtcNow; private ElsUnredeemedScale() { } public static ElsUnredeemedScale Create(DateOnly stdDt, string stndBassetCd, string secnTpcd, string? bassetContent, int? unredSecncnt, decimal? unredRema) { if (string.IsNullOrWhiteSpace(stndBassetCd)) { throw new ArgumentException("stndBassetCd required", nameof(stndBassetCd)); } return new ElsUnredeemedScale { StdDt = stdDt, StndBassetCd = stndBassetCd.Trim(), SecnTpcd = secnTpcd.Trim(), BassetContent = Trimmed(bassetContent), UnredSecncnt = unredSecncnt, UnredRema = unredRema }; } /// 재수집 반영 — 변경 필드가 있을 때만 UpdatedAt 갱신 (자연키 StdDt/StndBassetCd/SecnTpcd 은 불변) public void Update(string? bassetContent, int? unredSecncnt, decimal? unredRema) { var changed = false; changed |= Set(Trimmed(bassetContent), BassetContent, v => BassetContent = v); changed |= Set(unredSecncnt, UnredSecncnt, v => UnredSecncnt = v); changed |= Set(unredRema, UnredRema, v => UnredRema = 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; } }