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