using System.ComponentModel.DataAnnotations; namespace Domain.Entities.Stocks; /// /// SEIBro 채권 발행내역 (getBondIssuInfo) — 회사채·주식관련사채 발행종목 (Wave 4). 자연키 UNIQUE (Isin). /// BondMaster(getBondStatInfo) rolling 의 발견 소스 — 발행일(ISSU_DT) 날짜 스윕으로 신규 ISIN 을 찾는다. /// public class BondIssuance { [Key] public int ID { get; private set; } /// 발행일자 (ISSU_DT) public DateOnly IssuDt { get; private set; } /// 발행회사고객번호 (ISSUCO_CUSTNO) public int? IssucoCustno { get; private set; } /// 발행회사 명칭 (ISSUCO_CUST_NM) public string? IssucoCustNm { get; private set; } /// 종목코드 (ISIN) public string Isin { get; private set; } = default!; /// 한글종목명 (KOR_SECN_NM) public string? KorSecnNm { get; private set; } public DateTime UpdatedAt { get; private set; } = DateTime.UtcNow; private BondIssuance() { } public static BondIssuance Create(DateOnly issuDt, int? issucoCustno, string? issucoCustNm, string isin, string? korSecnNm) { if (string.IsNullOrWhiteSpace(isin)) { throw new ArgumentException("isin required", nameof(isin)); } return new BondIssuance { IssuDt = issuDt, IssucoCustno = issucoCustno, IssucoCustNm = Trimmed(issucoCustNm), Isin = isin.Trim(), KorSecnNm = Trimmed(korSecnNm) }; } /// 재수집 반영 — 변경 필드가 있을 때만 UpdatedAt 갱신 (자연키 Isin 은 불변) public void Update(DateOnly issuDt, int? issucoCustno, string? issucoCustNm, string? korSecnNm) { var changed = false; changed |= Set(issuDt, IssuDt, v => IssuDt = v); changed |= Set(issucoCustno, IssucoCustno, v => IssucoCustno = v); changed |= Set(Trimmed(issucoCustNm), IssucoCustNm, v => IssucoCustNm = v); changed |= Set(Trimmed(korSecnNm), KorSecnNm, v => KorSecnNm = 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; } }