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