using System.ComponentModel.DataAnnotations; namespace Domain.Entities.Stocks; /// /// SEIBro 파생결합증권 상환조건 (getRedCondiInfo) — 중간평가일·상환조건·계산식 (Wave 5). 자연키 UNIQUE (Isin, RedCondiTpcd, ValatNtimesSeq). /// rolling per-ISIN(DerivMaster 있는 것). 상환조건구분(1중간평가/2만기)×평가횟수(ValatNtimesSeq)별 조건문·계산식 다수 행. /// ⚠️ 응답에 ISIN 이 없어(요청 파라미터로만 받음) 배치가 요청 ISIN 을 스탬핑한다. /// 조건/계산식은 최대 1000자 자유 텍스트(VARCHAR2(1000)). /// public class DerivRedemptionCondition { [Key] public int ID { get; private set; } /// 종목코드 (ISIN, 스탬핑) public string Isin { get; private set; } = default!; /// 상환조건구분코드 (RED_CONDI_TPCD) — 1중간평가 2만기상환 public string RedCondiTpcd { get; private set; } = default!; /// 평가횟수일련번호 (VALAT_NTIMES_SEQ) public int ValatNtimesSeq { get; private set; } /// 중간평가지급일자 (MID_VALAT_PAY_DT) public DateOnly? MidValatPayDt { get; private set; } /// 중간평가시작일자 (MID_VALAT_BEGIN_DT) public DateOnly? MidValatBeginDt { get; private set; } /// 중간평가종료일자 (MID_VALAT_EXPRY_DT) public DateOnly? MidValatExpryDt { get; private set; } /// 상환조건내용 (RED_CONDI_CONTENT) — 최대 1000자 public string? RedCondiContent { get; private set; } /// 상환계산식내용 (RED_FORMULA_CONTENT) — 최대 1000자 public string? RedFormulaContent { get; private set; } public DateTime UpdatedAt { get; private set; } = DateTime.UtcNow; private DerivRedemptionCondition() { } public static DerivRedemptionCondition Create( string isin, string redCondiTpcd, int valatNtimesSeq, DateOnly? midValatPayDt, DateOnly? midValatBeginDt, DateOnly? midValatExpryDt, string? redCondiContent, string? redFormulaContent) { if (string.IsNullOrWhiteSpace(isin)) { throw new ArgumentException("isin required", nameof(isin)); } return new DerivRedemptionCondition { Isin = isin.Trim(), RedCondiTpcd = redCondiTpcd.Trim(), ValatNtimesSeq = valatNtimesSeq, MidValatPayDt = midValatPayDt, MidValatBeginDt = midValatBeginDt, MidValatExpryDt = midValatExpryDt, RedCondiContent = Trimmed(redCondiContent), RedFormulaContent = Trimmed(redFormulaContent) }; } /// 재수집 반영 — 변경 필드가 있을 때만 UpdatedAt 갱신 (자연키 Isin/RedCondiTpcd/ValatNtimesSeq 은 불변) public void Update( DateOnly? midValatPayDt, DateOnly? midValatBeginDt, DateOnly? midValatExpryDt, string? redCondiContent, string? redFormulaContent) { var changed = false; changed |= Set(midValatPayDt, MidValatPayDt, v => MidValatPayDt = v); changed |= Set(midValatBeginDt, MidValatBeginDt, v => MidValatBeginDt = v); changed |= Set(midValatExpryDt, MidValatExpryDt, v => MidValatExpryDt = v); changed |= Set(Trimmed(redCondiContent), RedCondiContent, v => RedCondiContent = v); changed |= Set(Trimmed(redFormulaContent), RedFormulaContent, v => RedFormulaContent = 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; } }