using System.ComponentModel.DataAnnotations; using Domain.Entities.Stocks.ValueObject; namespace Domain.Entities.Stocks; /// /// 일별 금리 (한국수출입은행 OpenAPI AP02 대출금리 / AP03 국제금리) — (RateType, ItemName, TradeDate) UNIQUE. /// 두 종류를 한 테이블에 담고 RateType 으로 구분한다. koreaexim 금리 응답은 { cur_nm(항목명), … } 형태로 /// 항목명(예: "리보 1개월", "우대금리") 별 1행이 오며 수치 필드가 응답에 따라 다르므로 대표 수치를 Rate 로 보관한다. /// - ItemName ← cur_nm (또는 대응 항목명 필드), Rate ← 해당 금리 수치(% — 천단위 콤마/빈값 방어, 미제공 시 null). /// public class InterestRate { [Key] public long ID { get; private set; } /// 금리 종류 (1=대출금리 AP02, 2=국제금리 AP03) public RateType RateType { get; private set; } /// 항목명 (cur_nm 등) — 예: "리보 1개월", "우대금리" public string ItemName { get; private set; } = default!; /// 거래일 (searchdate) public DateOnly TradeDate { get; private set; } /// 금리 % — 미제공/미고시 시 null public decimal? Rate { get; private set; } public DateTime CreatedAt { get; private set; } = DateTime.UtcNow; private InterestRate() { } public static InterestRate Create(RateType rateType, string itemName, DateOnly tradeDate, decimal? rate) { if (!Enum.IsDefined(rateType)) { throw new ArgumentOutOfRangeException(nameof(rateType)); } if (string.IsNullOrWhiteSpace(itemName)) { throw new ArgumentException("itemName required", nameof(itemName)); } return new InterestRate { RateType = rateType, ItemName = itemName.Trim(), TradeDate = tradeDate, Rate = rate }; } /// 동일 (RateType, ItemName, TradeDate) 재수집 시 값 갱신 (upsert) public void Update(decimal? rate) { Rate = rate; } }