using System.ComponentModel.DataAnnotations; namespace Domain.Entities.Stocks; /// /// SEIBro CD 종목 정보 (getCDInfo) — 발행금액·할인율·이자지급방식·만기 (Wave 4). PK Isin. /// ⚠️ 실샘플 fixture 가 result="0"(빈) 이라 필드 매핑은 채권.md 스펙 기준 — 운영 첫 수집 시 로그로 확인. /// rolling per-ISIN 대상 = ShortTermIssuance 발견분 중 SECN_TPCD=13(CD). /// public class CdMaster { /// 종목코드 (ISIN) — PK [Key] [MaxLength(12)] public string Isin { get; private set; } = default!; /// 발행사 번호 (ISSUCO_CUSTNO) public int? IssucoCustno { get; private set; } /// 한글종목명 (KOR_SECN_NM) public string? KorSecnNm { get; private set; } /// 발행통화코드 (ISSU_CUR_CD) — KRW public string? IssuCurCd { get; private set; } /// 최초발행금액 (FIRST_ISSU_AMT) public decimal? FirstIssuAmt { get; private set; } /// 발행방법코드 (ISSU_WHCD) public string? IssuWhcd { get; private set; } /// 액면금액 (FACE_AMT) public decimal? FaceAmt { get; private set; } /// 매출금액 (SALE_AMT) public decimal? SaleAmt { get; private set; } /// 할인율 (DISCN_RATE) public decimal? DiscnRate { get; private set; } /// 이자지급방식구분코드 (INT_PAY_MANN_TPCD) — 1할인식 2부리식 public string? IntPayMannTpcd { get; private set; } /// 발행일자 (ISSU_DT) public DateOnly? IssuDt { get; private set; } /// 만기일자 (XPIR_DT) — CD 상환일 public DateOnly? XpirDt { get; private set; } /// 전자증권 여부 (ELTSC_YN) public bool? EltscYn { get; private set; } public DateTime UpdatedAt { get; private set; } = DateTime.UtcNow; private CdMaster() { } public static CdMaster Create( string isin, int? issucoCustno, string? korSecnNm, string? issuCurCd, decimal? firstIssuAmt, string? issuWhcd, decimal? faceAmt, decimal? saleAmt, decimal? discnRate, string? intPayMannTpcd, DateOnly? issuDt, DateOnly? xpirDt, bool? eltscYn) { if (string.IsNullOrWhiteSpace(isin)) { throw new ArgumentException("isin required", nameof(isin)); } var entity = new CdMaster { Isin = isin.Trim() }; entity.Apply(issucoCustno, korSecnNm, issuCurCd, firstIssuAmt, issuWhcd, faceAmt, saleAmt, discnRate, intPayMannTpcd, issuDt, xpirDt, eltscYn); return entity; } /// 재수집 반영 (PK Isin 은 불변) — 변경 시에만 UpdatedAt public void Update( int? issucoCustno, string? korSecnNm, string? issuCurCd, decimal? firstIssuAmt, string? issuWhcd, decimal? faceAmt, decimal? saleAmt, decimal? discnRate, string? intPayMannTpcd, DateOnly? issuDt, DateOnly? xpirDt, bool? eltscYn) { Apply(issucoCustno, korSecnNm, issuCurCd, firstIssuAmt, issuWhcd, faceAmt, saleAmt, discnRate, intPayMannTpcd, issuDt, xpirDt, eltscYn); } private void Apply( int? issucoCustno, string? korSecnNm, string? issuCurCd, decimal? firstIssuAmt, string? issuWhcd, decimal? faceAmt, decimal? saleAmt, decimal? discnRate, string? intPayMannTpcd, DateOnly? issuDt, DateOnly? xpirDt, bool? eltscYn) { var changed = false; changed |= Set(issucoCustno, IssucoCustno, v => IssucoCustno = v); changed |= Set(Trimmed(korSecnNm), KorSecnNm, v => KorSecnNm = v); changed |= Set(Trimmed(issuCurCd), IssuCurCd, v => IssuCurCd = v); changed |= Set(firstIssuAmt, FirstIssuAmt, v => FirstIssuAmt = v); changed |= Set(Trimmed(issuWhcd), IssuWhcd, v => IssuWhcd = v); changed |= Set(faceAmt, FaceAmt, v => FaceAmt = v); changed |= Set(saleAmt, SaleAmt, v => SaleAmt = v); changed |= Set(discnRate, DiscnRate, v => DiscnRate = v); changed |= Set(Trimmed(intPayMannTpcd), IntPayMannTpcd, v => IntPayMannTpcd = v); changed |= Set(issuDt, IssuDt, v => IssuDt = v); changed |= Set(xpirDt, XpirDt, v => XpirDt = v); changed |= Set(eltscYn, EltscYn, v => EltscYn = 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; } }